字符串长度评估不正确

Jus*_*tch 7 c# string wcf

我的同事和我正在调试他正在处理的WCF服务中的问题,其中字符串的长度未被正确评估.他正在运行此方法来对其WCF服务中的方法进行单元测试:

// Unit test method
public void RemoveAppGroupTest()
{
    string addGroup = "TestGroup";
    string status = string.Empty;
    string message = string.Empty;

    appActiveDirectoryServicesClient.RemoveAppGroup("AOD", addGroup, ref status, ref message);
}


// Inside the WCF service
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public void RemoveAppGroup(string AppName, string GroupName, ref string Status, ref string Message)
{
    string accessOnDemandDomain = "MyDomain";

    RemoveAppGroupFromDomain(AppName, accessOnDemandDomain, GroupName, ref Status, ref Message);
}

public AppActiveDirectoryDomain(string AppName, string DomainName)
{
    if (string.IsNullOrEmpty(AppName))
    {
        throw new ArgumentNullException("AppName", "You must specify an application name");
    }
}
Run Code Online (Sandbox Code Playgroud)

我们试图进入.NET源代码以查看string.IsNullOrEmpty接收的值,但是当我们尝试评估变量时,IDE打印了此消息:'无法获取本地或参数'值的值,因为此指令不可用指针,可能是因为它已被优化掉了.(所涉及的项目均未启用优化).因此,我们决定在长度检查之前尝试在方法本身内部明确设置变量的值 - 但这没有帮助.

// Lets try this again.
public AppActiveDirectoryDomain(string AppName, string DomainName)
{
    // Explicitly set the value for testing purposes.
    AppName = "AOD";

    if (AppName == null)
    {
        throw new ArgumentNullException("AppName", "You must specify an application name");
    }

    if (AppName.Length == 0)
    {
        // This exception gets thrown, even though it obviously isn't a zero length string.
        throw new ArgumentNullException("AppName", "You must specify an application name");
    }
}
Run Code Online (Sandbox Code Playgroud)

我们真的在这个问题上脱颖而出.有没有其他人经历过这样的行为?有关调试的提示吗?


这是AppActiveDirectoryDomain行为发生的对象的MSIL :

.method public hidebysig specialname rtspecialname instance void .ctor(string AppName, string DomainName) cil managed
{
.maxstack 5
.locals init (
    [0] class [System]System.Net.NetworkCredential ldapCredentials,
    [1] string[] creds,
    [2] string userName,
    [3] class [mscorlib]System.ArgumentNullException exc,
    [4] class [System.DirectoryServices]System.DirectoryServices.ActiveDirectory.DirectoryContext directoryContext,
    [5] class [System.DirectoryServices]System.DirectoryServices.ActiveDirectory.Domain domain,
    [6] class [System.DirectoryServices.Protocols]System.DirectoryServices.Protocols.LdapException V_6,
    [7] class [mscorlib]System.Exception V_7,
    [8] bool CS$4$0000,
    [9] char[] CS$0$0001,
    [10] string[] CS$0$0002)
L_0000: ldarg.0 
L_0001: ldsfld string [mscorlib]System.String::Empty
L_0006: stfld string MyNamespace.MyClass.AppActiveDirectoryDomain::appOU
L_000b: ldarg.0 
L_000c: call instance void [mscorlib]System.Object::.ctor()
L_0011: nop 
L_0012: nop 
L_0013: ldstr "AOD"
L_0018: call bool [mscorlib]System.String::IsNullOrEmpty(string)
L_001d: ldc.i4.0 
L_001e: ceq 
L_0020: stloc.s CS$4$0000
L_0022: ldloc.s CS$4$0000
L_0024: brtrue.s L_0037
L_0026: nop 
L_0027: ldstr "AppName"
L_002c: ldstr "You must specify an application name"
L_0031: newobj instance void [mscorlib]System.ArgumentNullException::.ctor(string, string)
L_0036: throw
Run Code Online (Sandbox Code Playgroud)

string.IsNullOrEmpty电话的MSIL :

.method public hidebysig static bool IsNullOrEmpty(string 'value') cil managed
{
    .maxstack 8
    L_0000: ldarg.0 
    L_0001: brfalse.s L_000d
    L_0003: ldarg.0 
    L_0004: callvirt instance int32 System.String::get_Length()
    L_0009: ldc.i4.0 
    L_000a: ceq 
    L_000c: ret 
    L_000d: ldc.i4.1 
    L_000e: ret 
}
Run Code Online (Sandbox Code Playgroud)

编辑:

以下是抛出ArgumentNullException时"Watch"窗口中变量的屏幕截图:http://imgur.com/xQm4J.png

另外,第二个屏幕截图显示了在检查字符串长度时抛出的异常,在明确声明5行之后:http://imgur.com/lSrk9.png

更新#3:我们尝试更改局部变量的名称,并通过空检查和长度检查,但在调用时失败string.IsNullOrEmpty.请参见此屏幕截图:http://imgur.com/Z57AA.png.


对策:

  • 我们不使用任何可以修改MSIL的工具.我们已经执行了清理,并且还手动删除了构建目录中的所有文件,并强制重建...相同的结果.

  • 以下语句的计算结果为true,并输入if块: if (string.IsNullOrEmpty("AOD")) { /* */ }.

  • 构造函数的调用方式如下:

    try { using (AppActiveDirectoryDomain domain = new AppActiveDirectoryDomain(AppName, DomainName)) { } }

这立即在WCF服务方法本身内; AppName和DomainName是调用的参数.即使绕过这些参数并使用新字符串,我们仍然会得到错误.


Jus*_*tch 0

事实证明这是一个 64 位问题。或者至少它\xe2\x80\x99只是运行64位时的问题。在 64 位操作系统上的 IIS 7.0 中,默认情况下所有网站都托管在 64 位进程中。如果我们将服务设置为托管在 32 位进程中,问题就会消失。

\n