2009-09-25 6 views
1

PowerShell 스크립트에서 일부 Win32 API를 직접 호출하려고합니다. 내가 PowerShell의 사용이를 선언하는 방법을 확실하지 오전 적절한 declarations for C#을 발견하지만,PowerShell에서 WNetAddConnection2 호출

$cp = New-Object Microsoft.CSharp.CSharpCodeProvider 
$cpar = New-Object System.CodeDom.Compiler.CompilerParameters 

$Code = @" 
using System; 
using System.Runtime.InteropServices; 
namespace Win32Api 
{ 
    public class Net 
    { 
     [DllImport("mpr.dll", EntryPoint = "WNetAddConnection")] 
     public static extern uint Map(string lpRemoteName, string lpPassword, string lpLocalName); 
     [DllImport("mpr.dll", EntryPoint = "WNetCancelConnection")] 
     public static extern uint Delete(string lpName, byte fForce);  
    } 
} 
"@ 

$cp.CompileAssemblyFromSource($cpar, $code) 
[Win32Api.Net]::Map("\\REMKOLAPTOP\C$", $null, "W:") 

가 지금은 WNetAddConnection2 같은 일을하고 싶습니다 : 나는 아래의 코드와 WNetAddConnection 작업을 할 수 있었다. 그래서 내 질문은 : 적절한 "번역"이고 API를 호출하는 예제는 훌륭합니다.

내가 아래와 같이 이외의 API 메소드를 사용하지 않음을 유의하시기 바랍니다 :

$net = $(New-Object -Com WScript.Network) 
$net.MapNetworkDrive("u:", "\\computer\share") 

답변

4

내가 PowerShell을 2.0 작업에 다음 코드를 얻을 수있었습니다. 또한 Windows 오류 코드를 메시지로 변환하는 하나의 PSCX (http://pscx.codeplex.com) 함수를 사용합니다. 또한 사용자 이름과 암호를 입력하라는 대화식 옵션을 설정하는 옵션을 설정했습니다. PowerShell의 Get-Credential cmdlet을 사용하여 동일한 작업을 수행 할 수있는 방법을 보여주는 주석 처리 된 스크립트가 포함되어 있습니다.

BTW 사용자 이름/암호를 함수를 통해 함수에 제공하면 주문이 올바르게 수행됩니다. 암호 뒤에 username이 오는 것이 좋습니다. 내가 주문을 잘못 이해했다고 생각할 때까지 10 분 동안 나를 물었다. 도! 이 같은 interop 도움말에 대한 또 다른 맛있는 음식은 체크 아웃 http://www.pinvoke.net해야합니다. 어쨌든, 이것이 도움이되기를 바랍니다.

$WNetAddConnection2WrapperSource = @' 
using System; 
using System.Runtime.InteropServices; 

namespace Win32Api { 
    public enum ResourceScope { 
     RESOURCE_CONNECTED = 1, 
     RESOURCE_GLOBALNET, 
     RESOURCE_REMEMBERED, 
     RESOURCE_RECENT, 
     RESOURCE_CONTEXT 
    }; 

    public enum ResourceType { 
     RESOURCETYPE_ANY, 
     RESOURCETYPE_DISK, 
     RESOURCETYPE_PRINT, 
     RESOURCETYPE_RESERVED = 8 
    }; 

    [Flags] 
    public enum ResourceUsage { 
     RESOURCEUSAGE_CONNECTABLE = 0x00000001, 
     RESOURCEUSAGE_CONTAINER = 0x00000002, 
     RESOURCEUSAGE_NOLOCALDEVICE = 0x00000004, 
     RESOURCEUSAGE_SIBLING = 0x00000008, 
     RESOURCEUSAGE_ATTACHED = 0x00000010, 
     RESOURCEUSAGE_ALL = (RESOURCEUSAGE_CONNECTABLE | 
          RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED), 
    }; 

    public enum ResourceDisplayType { 
     RESOURCEDISPLAYTYPE_GENERIC, 
     RESOURCEDISPLAYTYPE_DOMAIN, 
     RESOURCEDISPLAYTYPE_SERVER, 
     RESOURCEDISPLAYTYPE_SHARE, 
     RESOURCEDISPLAYTYPE_FILE, 
     RESOURCEDISPLAYTYPE_GROUP, 
     RESOURCEDISPLAYTYPE_NETWORK, 
     RESOURCEDISPLAYTYPE_ROOT, 
     RESOURCEDISPLAYTYPE_SHAREADMIN, 
     RESOURCEDISPLAYTYPE_DIRECTORY, 
     RESOURCEDISPLAYTYPE_TREE, 
     RESOURCEDISPLAYTYPE_NDSCONTAINER 
    }; 

    [StructLayout(LayoutKind.Sequential)] 
    public class NetResource { 
     public ResourceScope Scope; 
     public ResourceType Type; 
     public ResourceDisplayType DisplayType; 
     public ResourceUsage Usage; 
     public string LocalName; 
     public string RemoteName; 
     public string Comment; 
     public string Provider; 
    }; 

    [Flags] 
    public enum AddConnectionOptions { 
     CONNECT_UPDATE_PROFILE = 0x00000001, 
     CONNECT_UPDATE_RECENT = 0x00000002, 
     CONNECT_TEMPORARY  = 0x00000004, 
     CONNECT_INTERACTIVE = 0x00000008, 
     CONNECT_PROMPT   = 0x00000010, 
     CONNECT_NEED_DRIVE  = 0x00000020, 
     CONNECT_REFCOUNT  = 0x00000040, 
     CONNECT_REDIRECT  = 0x00000080, 
     CONNECT_LOCALDRIVE  = 0x00000100, 
     CONNECT_CURRENT_MEDIA = 0x00000200, 
     CONNECT_DEFERRED  = 0x00000400, 
     CONNECT_RESERVED  = unchecked((int)0xFF000000), 
     CONNECT_COMMANDLINE = 0x00000800, 
     CONNECT_CMD_SAVECRED = 0x00001000, 
     CONNECT_CRED_RESET  = 0x00002000 
    } 

    public static class NativeMethods { 
     [DllImport("mpr.dll", EntryPoint="WNetAddConnection2")]  
     public static extern int WNetAddConnection2(
      NetResource netResource, string password, 
      string username, AddConnectionOptions options); 
    } 
} 
'@ 

Add-Type -TypeDefinition $WNetAddConnection2WrapperSource 

$netResource = new-object Win32Api.NetResource 
$netResource.Type = [Win32Api.ResourceType]::RESOURCETYPE_DISK 
$netResource.LocalName = 'P:' 
$netResource.RemoteName = '\\AnotherPC\C' 

# Get username and password 
#$cred = Get-Credential 
#$username = $cred.UserName 
#$bstr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($cred.Password) 
#$password = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($bstr) 
#[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr) 

$opts = [Win32Api.AddConnectionOptions]::CONNECT_INTERACTIVE -bor 
     [Win32Api.AddConnectionOptions]::CONNECT_PROMPT -bor 
     [Win32Api.AddConnectionOptions]::CONNECT_UPDATE_PROFILE 

$res = [Win32Api.NativeMethods]::WNetAddConnection2($netResource, 0, 0, $opts) 
if ($res -ne 0) { 
    # This function comes with PSCX http://pscx.codeplex.com 
    Get-ExceptionForWin32 $res 
    throw "Failed to connect" 
} 
# Display results 
net use 
+0

PS1.0에서 오류가 발생하지 않지만 아직 작동하지 않습니다. 스크립트가 무기한 대기하는 것 같습니다. 내 코드에 비해 나는 CompileAssemblyFromSource ($ cpar, $ code)를 놓친다. 그래서 나는 그것을 적응시키고 그것이 작동 하는지를 보게 될 것이다. 이제 귀하의 솔루션을 유용하다고 표시했습니다. – Remko

+0

코드가 PS2.0에서 작동합니다. $ res = [Win32Api.NativeMethods] :: WNetAddConnection2 ($ netResource, $ null, $ null, $ opts)는 작동하지 않습니다. 어디서 작동합니까? $ res = [Win32Api.NativeMethods] :: WNetAddConnection2 ($ netResource, 0, 0, $ opts) – Remko

+0

나중에 일하게 된 것을 기쁘게 생각합니다. 어리석은 서명에 잠시 나간 것. 난 그냥 * 엉덩이 * 사용자 이름이 비밀 번호가 뒤따른 것 같아. –

관련 문제