C# 安全属性什么时候改变的?为什么?
我有一些代码使用p/Invoke启动流程并捕获标准输出。(为什么我们使用P/Invoke而不是C# 安全属性什么时候改变的?为什么?,c#,.net,process,pinvoke,C#,.net,Process,Pinvoke,我有一些代码使用p/Invoke启动流程并捕获标准输出。(为什么我们使用P/Invoke而不是System.Diagnostics.Process来实现这一点的故事既长又复杂;可以说这是一项要求。)它在生产中已经在重载下工作了近一年,使用它的测试总是通过的 今天早上虽然我做了测试,但都失败了。我不能确定我上一次在今天早上(2014年5月15日)之前进行测试的时间,但我相信是2014年4月24日。测试当时通过了,但今天早上没有通过。我收到了“PinvokeStackDistancert”错误消息,
System.Diagnostics.Process
来实现这一点的故事既长又复杂;可以说这是一项要求。)它在生产中已经在重载下工作了近一年,使用它的测试总是通过的
今天早上虽然我做了测试,但都失败了。我不能确定我上一次在今天早上(2014年5月15日)之前进行测试的时间,但我相信是2014年4月24日。测试当时通过了,但今天早上没有通过。我收到了“PinvokeStackDistancert”错误消息,因此我做了一些研究,最终发现extern
方法(CreatePipe
在本例中)使用的一个结构的签名不正确。我改了,考试又开始通过了
我很高兴找到了修复方案,但我担心部署问题为什么结构的签名会改变?我没有升级我的操作系统或任何东西-我在4/24上运行Windows 7 x64,现在仍在运行它。(部署环境是Windows Server 2012。)从那以后,我安装(并卸载)了一些应用程序,但它们是轻量级的第三方工具,而不是Microsoft或系统组件。我认为是Windows Update修补程序造成的,但我不知道是哪一个
要清楚,在我自己的代码中,我所做的更改是:
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public UInt32 nLength;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}
为此:
[StructLayout(LayoutKind.Sequential)]
internal class SECURITY_ATTRIBUTES
{
public int nLength = 12;
public IntPtr lpSecurityDescriptor = IntPtr.Zero;
public bool bInheritHandle;
}
我需要确保,当我部署到生产环境时,我为使代码在我的机器上运行所做的更改不会破坏应用程序。是否有人知道如何确定变更的必要性,以及如何确定生产环境是否需要变更 编辑: 以下是为标准输出打开管道的代码:
private PipeInfo CreatePipe()
{
PipeInfo pipeInfo = new PipeInfo();
SafeFileHandle safeFileHandle = null;
try
{
Native.SECURITY_ATTRIBUTES pipeAttributes = new Native.SECURITY_ATTRIBUTES();
pipeAttributes.bInheritHandle = true;
if (!Native.CreatePipe(out safeFileHandle, out pipeInfo.ChildHandle, pipeAttributes, 0) || safeFileHandle.IsInvalid || pipeInfo.ChildHandle.IsInvalid)
{
throw new Win32Exception();
}
if (!Native.DuplicateHandle(new HandleRef(this, Native.GetCurrentProcess()), safeFileHandle, new HandleRef(this, Native.GetCurrentProcess()), out pipeInfo.ParentHandle, 0, false, 2))
{
throw new Win32Exception();
}
}
finally
{
if (safeFileHandle != null && !safeFileHandle.IsInvalid)
{
safeFileHandle.Close();
}
}
return pipeInfo;
}
我不能完全相信这个代码,我基本上是从
只是为了明确时间线:
- 2013年5月-使用第一个版本的
SECURITY\u属性编写
代码CreatePipe
- 2013年6月-部署;此后,代码一直在成功运行
- 2014年4月-在未进行任何更改的情况下,代码开始抛出堆栈不平衡错误
- 2014年5月-我更改为第二版本的
,错误消失安全属性
安全属性从未改变。你真的不应该使用魔法常数12。使用
Marshal.SizeOf
。我猜你在代码中更改了其他内容。查阅您的修订控制历史记录,找出x64的0.12是不正确的值。此外,您描述的更改不会改变您是否获得堆栈不平衡。所以你确实需要弄清楚事实。@DavidHeffernan,我知道解决方案本身的代码没有任何变化,这就是为什么我怀疑热修复程序改变了解决方案的底层依赖关系。此外,事实是,第一个代码块会产生堆栈不平衡,但在按照所述方式仅更改此结构/类之后,错误就会消失。所以事实是直截了当的,他们只是不加起来;这就是我的问题。(感谢您提醒我不要使用魔法常数;我将研究如何使用SizeOf
)因此,我从未发现发生了什么。最后,我告诉我们的部署团队,我们需要在服务器上安装,然后我们成功地将其部署到QA和生产环境中。我的理论是,一些热修复程序使得nLength
不再被设置为默认值,因此我必须在我的代码中执行,这可能会更好。
[StructLayout(LayoutKind.Sequential)]
internal class SECURITY_ATTRIBUTES {
#if !SILVERLIGHT
// We don't support ACL's on Silverlight nor on CoreSystem builds in our API's.
// But, we need P/Invokes to occasionally take these as parameters. We can pass null.
public int nLength = 12;
public SafeLocalMemHandle lpSecurityDescriptor = new SafeLocalMemHandle(IntPtr.Zero, false);
public bool bInheritHandle = false;
#endif // !SILVERLIGHT
}
internal static class NativeMethods
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CreatePipe(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe,
IntPtr lpPipeAttributes, int nSize);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern bool DuplicateHandle(IntPtr hSourceProcessHandle, SafeHandle hSourceHandle,
IntPtr hTargetProcess, out SafeFileHandle targetHandle, int dwDesiredAccess,
bool bInheritHandle, int dwOptions);
[StructLayout(LayoutKind.Sequential)]
public struct PIPE_SECURITY_ATTRIBUTES
{
public DWORD nLength;
public IntPtr lpSecurityDescriptor;
[MarshalAs(UnmanagedType.Bool)]
public bool bInheritHandle;
}
public static void CreatePipe(out SafeFileHandle parentHandle, out SafeFileHandle childHandle, bool parentInputs)
{
PIPE_SECURITY_ATTRIBUTES lpPipeAttributes = new PIPE_SECURITY_ATTRIBUTES();
lpPipeAttributes.nLength = (DWORD)Marshal.SizeOf(lpPipeAttributes);
lpPipeAttributes.bInheritHandle = true;
lpPipeAttributes.lpSecurityDescriptor = IntPtr.Zero;
IntPtr attr = Marshal.AllocHGlobal(Marshal.SizeOf(lpPipeAttributes));
Marshal.StructureToPtr(lpPipeAttributes, attr, true);
SafeFileHandle hWritePipe = null;
try
{
if (parentInputs)
CreatePipeWithSecurityAttributes(out childHandle, out hWritePipe, attr, 0);
else
CreatePipeWithSecurityAttributes(out hWritePipe, out childHandle, attr, 0);
if (!DuplicateHandle(GetCurrentProcess(), hWritePipe, GetCurrentProcess(), out parentHandle, 0, false, 2))
throw new Exception();
}
finally
{
if ((hWritePipe != null) && !hWritePipe.IsInvalid)
{
hWritePipe.Close();
}
}
}
public static void CreatePipeWithSecurityAttributes(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe,
IntPtr lpPipeAttributes, int nSize)
{
hReadPipe = null;
if ((!CreatePipe(out hReadPipe, out hWritePipe, lpPipeAttributes, nSize) || hReadPipe.IsInvalid) || hWritePipe.IsInvalid)
throw new Exception();
}
}