[英]P/Invoke SHSetKnownFolderPath Failing
I thought this would be a simple enough script.我认为这将是一个足够简单的脚本。 I came across this article about how to use powershell to redirect folders to OneDrive here: https://stealthpuppy.com/onedrive-intune-folder-redirection/
我在这里看到这篇关于如何使用 powershell 将文件夹重定向到 OneDrive 的文章: https://stealthpuppy.com/onedrive-intune-folder-redirection/
I realized this script would not work for me, as the way it is written it requires user context and cannot be run silently using Task Scheduler, so I set out to try and "rewrite" the script using a system context.我意识到这个脚本对我不起作用,因为它的编写方式需要用户上下文并且不能使用 Task Scheduler 静默运行,所以我开始尝试使用系统上下文“重写”脚本。 All seems to be working except for one chunk that I can't seem to understand.
除了我似乎无法理解的一大块之外,一切似乎都在工作。 I think it's C# and I'm only familiar with powershell. I am only concerned with redirecting the downloads folder, so his is what I have.
我认为它是 C#,我只熟悉 powershell。我只关心重定向下载文件夹,所以他就是我的。
#These are the potential GUIDs for the Downloads KFM path of the user
$Guids = $null
$Guids = @()
$Guids += [pscustomobject]@{
Guid = '{374DE290-123F-4565-9164-39C4925E467B}'
Paths = @()
}
$Guids += [pscustomobject]@{
Guid = '{7d83ee9b-2244-4e70-b1f5-5393042af1e4}'
Paths = @()
}
#Log Variables
$timestamp = Get-Date -Format o | ForEach-Object { $_ -replace ":", "." }
$LogPath = "$env:USERPROFILE\AppData\Local\Intune-PowerShell-Logs\OneDriveSync-$timestamp.txt"
Start-Transcript -Path $LogPath
$CurrentUsers = Get-ItemProperty -path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\*" | Where {($_.ProfileImagePath -notmatch '.NET') -and ($_.ProfileImagePath -notmatch 'Default') -and ($_.ProfileImagePath -match "Users")} | select ProfileImagePath,PSChildName
ForEach ($CurrentUser in $CurrentUsers)
{
$SourcePath = "$($CurrentUser.ProfileImagePath)\Downloads"
$Targetpath = "$($CurrentUser.ProfileImagePath)\OneDrive\Downloads"
$Rootpath = "HKU:\$($CurrentUser.PSChildName)"
$ShellFolderspath = "$RootPath\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
$UserShellFolderspath = "$Rootpath\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders"
#region 1 - Identify registry keys to update
New-PSDrive -Name HKU -PSProvider Registry -Root HKEY_USERS -ErrorAction SilentlyContinue
#Adding Downloads Guids to array
ForEach ($object in $Guids)
{
#Check Shell Folders Path
If ($Item = Get-ItemProperty $ShellFolderspath -Name $object.Guid -ErrorAction SilentlyContinue)
{
"$($object.guid) found in Shell Folders path"
$Object.paths += @($Item.PSpath)
}
#Check User Shell Folders Path
If ($Item = Get-ItemProperty $UserShellFolderspath -Name $object.Guid -ErrorAction SilentlyContinue)
{
"$($object.guid) found in User Shell Folders path"
$Object.paths += @($Item.PSpath)
}
}
#endregion
#region 2
# Define SHSetKnownFolderPath if it hasn't been defined already
$Type = ([System.Management.Automation.PSTypeName]'KnownFolders').Type
If (-not $Type)
{
$Signature = @'
[DllImport("shell32.dll")]
public extern static int SHSetKnownFolderPath(ref Guid folderId, uint flags, IntPtr token, [MarshalAs(UnmanagedType.LPWStr)] string path);
'@
$Type = Add-Type -MemberDefinition $Signature -Name 'KnownFolders' -Namespace 'SHSetKnownFolderPath' -PassThru
}
#Test if new directory exists
If (!(Test-Path -Path $Targetpath -PathType Container))
{
New-Item -Path $TargetPath -Type Directory -Force
}
#Validate the path
If (Test-Path $TargetPath -PathType Container)
{
#Call SHSetKnownFolderPath
#return $Type::SHSetKnownFolderPath([ref]$KnownFolders[$KnownFolder], 0, 0, $Path)
ForEach ($object in $Guids)
{
$result = $Type::SHSetKnownFolderPath([ref]$object.guid, 0, 0, $Targetpath)
If ($result -ne 0)
{
$errormsg = "Error redirecting $($Object.guid). Return code $($result) = $((New-Object System.ComponentModel.Win32Exception($result)).message)"
Throw $errormsg
}
}
}
Else
{
Throw New-Object System.IO.DirectoryNotFoundException "Could not find part of the path $Path."
}
#endregion
#region 3 - Set new downloads directory
ForEach ($Object in $Guids)
{
ForEach ($path in $object.paths)
{
Set-ItemProperty -Path $path -Name $object.Guid -Value $Targetpath -Verbose
}
}
#endregion
#region 4
#Move files from old directory to the new one
#Robocopy.exe "$SourcePath" "$Targetpath" /E /MOV /XJ /XF *.ini /R:1 /W:1 /NP
#endregion
#}
}
Stop-Transcript
All seems to work except that I get an error on line 74 that says, "Error redirecting {374DE290-123F-4565-9164-39C4925E467B}. Return code -2147024894 = The system cannot find the file specified"一切似乎都正常,除了我在第 74 行收到一条错误消息,“错误重定向 {374DE290-123F-4565-9164-39C4925E467B}。返回代码 -2147024894 = 系统找不到指定的文件”
I have spent almost an entire work day trying to tackle this problem and am getting nowhere.我几乎花了一整天的时间来解决这个问题,但一无所获。 Any help would be appreciated!
任何帮助,将不胜感激!
You have two problems:你有两个问题:
The immediate, technical problem: The system cannot find the file specified
implies that the specified KNOWNFOLDERID GUID is not recognized.直接的技术问题:
The system cannot find the file specified
意味着无法识别指定的KNOWNFOLDERID GUID。
{7d83ee9b-2244-4e70-b1f5-5393042af1e4}
, not the one mentioned in your error message, {374DE290-123F-4565-9164-39C4925E467B}
(the Downloads folder), that is unknown.{7d83ee9b-2244-4e70-b1f5-5393042af1e4}
,而不是错误消息中提到的{374DE290-123F-4565-9164-39C4925E467B}
(下载文件夹),这是未知的. A conceptual problem: You're trying to call SHSetKnownFolderPath
for specific users , which requires that you pass a so-called access token representing the user of interest as the hToken
argument.一个概念性问题:您正在尝试为特定用户调用
SHSetKnownFolderPath
,这要求您传递一个代表感兴趣用户的所谓访问令牌作为hToken
参数。
0
for hToken
, you're always updating for the current user.hToken
传递了0
,因此您总是在为当前用户更新。 If you want to avoid the additional complexity of obtaining access tokens representing other users via the LogonUser
WinAPI function , you can bypass SHSetKnownFolderPath
calls and write directly to the registry, as your code in part already does;如果您想避免通过
LogonUser
WinAPI function获取代表其他用户的访问令牌的额外复杂性,您可以绕过SHSetKnownFolderPath
调用并直接写入注册表,因为您的部分代码已经这样做了; however, note that while that should work as of this writing, doing so isdiscouraged and may at some point in the future stop working.但是,请注意,虽然在撰写本文时这应该有效,但不鼓励这样做,并且可能在将来的某个时候停止工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.