将C ++ / CLI代码转换为C#

时间:2009-09-26 21:40:34

标签: c# c++-cli

我正在尝试将此c ++ / cli代码翻译为c#

#pragma once
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tchar.h>

   using namespace System;
   using namespace System::Runtime::InteropServices;

    struct CREDENTIAL    
    {
        DWORD Flags;
        DWORD Type;
        LPSTR TargetName;
        LPSTR Comment;
        Runtime::InteropServices::ComTypes::FILETIME LastWritten;        
        DWORD CredentialBlobSize;
        LPBYTE CredentialBlob;
        DWORD Persist;
        DWORD AttributeCount;
        LPBYTE Attributes;
        LPSTR TargetAlias;
        LPWSTR UserName;
    };

    [DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet::Unicode)]
    extern BOOL CredEnumerate(LPCTSTR Filter, DWORD Flags, DWORD* count, CREDENTIAL*** Credentials);

    [DllImport("advapi32.dll")]
    extern VOID CredFree(LPVOID);

        int main( array<System::String^>^argv )
        {
            String^ credentialList = "";
            Int32 count = 0;
            CREDENTIAL** credentialCollection = 0;            

            if( CredEnumerate( _T("WindowsLive:name=*"), 0, (DWORD*)&count, &credentialCollection) )                        
            {
                for( Int32 n = 0; n < count; n++ )
                {
                    credentialList += "\n";
                    credentialList += "Username " + gcnew System::String( credentialCollection[n]->UserName ) + "\n";
                    credentialList += "Password: " + gcnew System::String( (LPWSTR)credentialCollection[n]->CredentialBlob ) + "\n";
                } 

                CredFree( &credentialCollection );
        Console::WriteLine(credentialList);

            }
        Console::ReadLine();
        }

这是我的c#代码..(我不确定CredEnumerate是如何工作的)

using System;
using System.Runtime.InteropServices;     // DLL support
using System.Collections.Generic;

public struct CREDENTIAL
{
    public UInt32 flags;
    public UInt32 type;
    public string targetName;
    public string comment;
    public System.Runtime.InteropServices.ComTypes.FILETIME lastWritten;
    public UInt32 credentialBlobSize;
    public IntPtr credentialBlob;
    public UInt32 persist;
    public UInt32 attributeCount;
    public IntPtr credAttribute;
    public string targetAlias;
    public string userName;
}

class Test
{        
    [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern bool CredEnumerate(string filter, int flag, out int count, out IntPtr
    pCredentials);

    static void Main()
    {
        try
        {
            int count = 0;
            IntPtr pCredentials = IntPtr.Zero;
            IntPtr[] credentials = null;
            bool ret = CredEnumerate("WindowsLive:name=*", 0, out count, out pCredentials);
            if (ret != false)
            {

                credentials = new IntPtr[count];
                IntPtr p = pCredentials;
                for (int n = 0; n < count; n++)
                {
                    if (Marshal.SizeOf(p) == 4) //32 bit CLR?
                        p = new IntPtr(p.ToInt32() + n);
                    else
                        p = new IntPtr(p.ToInt64() + n);
                    credentials[n]  = Marshal.ReadIntPtr(p);
                }

                List<CREDENTIAL> creds = new List<CREDENTIAL>(credentials.Length);
                foreach (var ptr in credentials)
                {
                    creds.Add((CREDENTIAL)Marshal.PtrToStructure(ptr, typeof(CREDENTIAL)));
                }

            }
        }
        catch (Exception x)
        {
            Console.WriteLine(x.ToString());
        }

        Console.ReadLine();
    }
}

我希望有人可以帮助我

2 个答案:

答案 0 :(得分:2)

这是非常可怕的代码,我怀疑CLI / C ++是对的。您应该查找结构的定义,例如

http://msdn.microsoft.com/en-us/library/aa374788(VS.85).aspx

然后在发布前正确清理代码。

我很想在凭证管理中使用this article中的代码

尽管如此,这仍然需要保留你似乎想要摆脱的CLI / C ++,所以我给它修好了。

现在这可以在我的机器上运行,我已经将它们一起攻击了......(注意:我已经删除了你的过滤器,所以我可以测试它)

[StructLayout(LayoutKind.Sequential)]
internal struct CREDENTIAL {
    public int Flags;
    public int Type;
    [MarshalAs(UnmanagedType.LPWStr)]
    public string TargetName;
    [MarshalAs(UnmanagedType.LPWStr)]
    public string Comment;
    public long LastWritten;
    public int CredentialBlobSize;
    public IntPtr CredentialBlob;
    public int Persist;
    public int AttributeCount;
    public IntPtr Attributes;
    [MarshalAs(UnmanagedType.LPWStr)]
    public string TargetAlias;
    [MarshalAs(UnmanagedType.LPWStr)]
    public string UserName;
}

然后阅读

try
{
    uint count;
    IntPtr pCredentials = IntPtr.Zero;
    IntPtr[] credentials;
    bool ret = CredEnumerateW("*", 0, out count, out pCredentials);
    if (ret)
    {
        credentials = new IntPtr[count];
        List<CREDENTIAL> creds = new List<CREDENTIAL>(credentials.Length);
        for(int i = 0; i < count; i++) {
            IntPtr structs= Marshal.ReadIntPtr(pCredentials, IntPtr.Size * i);
            CREDENTIAL c = (CREDENTIAL)Marshal.PtrToStructure(structs, typeof(CREDENTIAL));
            creds.Add(c);
        }
    }
}
catch (Exception x)
{
    Console.WriteLine(x.ToString());
}

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool CredEnumerateW(string filter, uint flag, out uint count, out IntPtr pCredentials);

它不会释放结构等。

答案 1 :(得分:0)

查看pinvoke.net它可能有一个如何调用CredEnumerate的示例