你可以在Powershell中使用DllImport(Add-type)而不需要强制转换吗?

时间:2017-05-03 15:37:09

标签: c# powershell casting dllimport

我正在尝试从Powershell使用.net的MoveFileEx函数,但是DllImport似乎需要将所有参数都转换为某种类型。

感谢http://poshcode.org/2196

,我有这段代码
$MOVEFILE_DELAY_UNTIL_REBOOT = 0x00000004
$memberDefinition = @'
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)]
public static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, int dwFlags);
'@
$type = Add-Type -Name MoveFileUtils -MemberDefinition $memberDefinition -PassThru

要在启动时移动文件,这样可以正常工作:

$result = $type::MoveFileEx($Path, $destination, $MOVEFILE_DELAY_UNTIL_REBOOT)

要在启动时删除文件,我认为这样可行。

$result = $type::MoveFileEx($Path, $null, $MOVEFILE_DELAY_UNTIL_REBOOT)

但是我收到了这个错误:

You cannot call a method on a null-valued expression. 
At line:2 char:1 + $result = $type::MoveFileEx($Path, $null, $MOVEFILE_DELAY_UNTIL_REBOOT) +
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~‌​~~~~~~~~~~~ + 
CategoryInfo : InvalidOperation: (:) [], RuntimeException + 
FullyQualifiedErrorId : InvokeMethodOnNull

这是因为lpNewFileName在上面的DllImport行中转换为字符串

有没有办法重新编写$ memberDefinition(也就是c#代码)以将lpNewFileName转换为字符串?

或者两次导入MoveFileEx函数,一个用lpNewFileName强制转换为字符串,第二个用lpNewFileName强制转换为null?

更新1:我试过这个

$NullValue = [NullString]::Value
$result = $type::MoveFileEx($Path, $NullValue, $MOVEFILE_DELAY_UNTIL_REBOOT)

并收到此错误:

You cannot call a method on a null-valued expression.
At line:4 char:6
+                     $result = $type::MoveFileEx($Path, $NullValue, $MOVEFILE_DELAY_UNTIL_REBOOT ...
+                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

看起来我需要在c#中编写一个包装函数来调用相同的MoveFileEx,具体取决于我是要移动还是删除文件。耶!

更新2 按要求:完全自包含的代码以演示问题。

$Path = "C:\ProgramData\DeleteMe.txt"
Set-Content -Path $Path -Value "Test file for you!"

$memberDefinition = @'
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)]
public static extern bool MoveFileEx(string lpExistingFileName, string lpNewFileName, int dwFlags);
'@
$type = Add-Type -Name MoveFileUtils -MemberDefinition $memberDefinition -PassThru

[Int32]$MOVEFILE_DELAY_UNTIL_REBOOT = 0x00000004
$NullValue = [NullString]::Value  #I read that c# may not like $null b/c c# sees $null as an object. (Stay buggy MS)
$result = $type::MoveFileEx($Path, $NullValue, $MOVEFILE_DELAY_UNTIL_REBOOT)
#If successful, PendingFileRenameOperations value is created at: 
# [HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Session Manager]
$Destination = "C:\ProgramData\DeleteMe.new"
$result = $type::MoveFileEx($Path, $Destination, $MOVEFILE_DELAY_UNTIL_REBOOT)

现在问题已经消失了!没有更多的错误。 WTH ..谢谢你?!

似乎 [NullString] :: Value 是关键但我第一次尝试时失败了。

0 个答案:

没有答案