如何在 Powershell 中编辑 Windows Store Apps 的 settings.dat 文件?
How can I edit the settings.dat file for Windows Store Apps in Powershell?
我正在自动部署一个 Windows 商店应用程序,我想自动设置用户通常会在设置超级按钮中配置的设置之一。我了解到设置存储在 settings.dat
文件中,可以在注册表中打开该文件。但这是一个二进制文件,我不知道如何通过 Powershell 编辑我想要的设置。这甚至是我可以做的事情还是不值得付出努力?谢谢
这就是特定设置的样子 regedit
据我所知,当注册表文件未加载到注册表中时,无法编辑它们。我玩了一会儿,找到了一种方法,但是您需要暂时将注册表文件加载到您的注册表中并在那里进行编辑。看来您需要使用 reg.exe
来执行此操作。
另一个问题是此注册表文件中使用的自定义 属性 类型(5f5e10c
而不是 REG_BINARY
)。 PowerShell and .NET 两个 API 似乎都无法加载或正确保存它们。我不得不导出密钥,在 .reg
文件中编辑它们,然后将它们导入回来。
另一个需要考虑的特性是所有编码值中包含的时间戳,如 this blog post 中所述。
这是我设法写的一个工作脚本,在评论中有额外的解释(你需要 运行 它作为管理员,否则加载注册表文件将失败):
# full path to the registry file to edit
$settingsFile = "c:\Users\Damir\AppData\Local\Packages3f4f59-2aa3-455b-8531-185f633c1ffe_ecet6zh215f6e\Settings\settings.dat"
# setting name to change
$settingKey = "ServerUrl"
# new setting value
$newValue = "http://prodserver.local/esign/"
# name of temporary .reg file
$regFile = ".\settings.reg"
# temporary registry location to import registry file into
$registryImportLocation = "HKLM\_TMP"
# prefix matching the setting in the .reg file
$settingKeyPattern = """$settingKey""="
# load the settings file into registry
reg load $registryImportLocation $settingsFile
# export the settings into .reg file
reg export $registryImportLocation $regFile
$fileContents = Get-Content $regFile
$finalContents = @()
$processing = $false
Foreach ($line in $fileContents)
{
If (-Not ($processing))
{
If ($line.StartsWith($settingKeyPattern))
{
# setting key found, stop copying file contents
$processing = $true
# read key value without its name
$oldSerializedValue = $line.Replace($settingKeyPattern, "")
}
Else
{
# setting key not found yet, copy old file contents to output
$finalContents += $line
}
}
else
{
# value can span multiple lines, trim leading spaces from non-first lines
$oldSerializedValue += $line.TrimStart(" ")
}
If ($processing)
{
If ($oldSerializedValue.EndsWith("\"))
{
# trailing \ indicates non-final line with key value
$oldSerializedValue = $oldSerializedValue.TrimEnd("\")
}
Else
{
# split key type and value
$match = $oldSerializedValue -match '(.*:)(.*)'
# final 8 bytes are timestamp of the value - don't modify
$timestamp = $matches[2].Substring($matches[2].Length - 23)
# encode new value in UTF-16
$newValueInBytes = [System.Text.Encoding]::Unicode.GetBytes($newValue)
# key name and type
$newValue = $settingKeyPattern + $matches[1]
# encode byte array into required string format
Foreach ($byte in $newValueInBytes)
{
$newValue += [System.Convert]::ToString($byte, 16).PadLeft(2, "0") + ","
}
# end null character string terminator
$newValue += "00,00," + $timestamp
$finalContents += $newValue
# reenable copying of the remaining file
$processing = $false
}
}
}
# dump new file contents to file
$finalContents | Out-File $regFile
# import the changed value into registry
reg import $regFile
# onload the registry file from registry
reg unload $registryImportLocation
# delete temporary file
Remove-Item $regFile
您需要对其进行一些修改以将其包含在您的部署过程中,但它应该可以帮助您入门。
编辑: 我写了一个 accompanying blog post describing the thought process behind the answer. It provides an even more in depth explanation and links to a PowerShell function implementation 包装上面的脚本。
我正在自动部署一个 Windows 商店应用程序,我想自动设置用户通常会在设置超级按钮中配置的设置之一。我了解到设置存储在 settings.dat
文件中,可以在注册表中打开该文件。但这是一个二进制文件,我不知道如何通过 Powershell 编辑我想要的设置。这甚至是我可以做的事情还是不值得付出努力?谢谢
这就是特定设置的样子 regedit
据我所知,当注册表文件未加载到注册表中时,无法编辑它们。我玩了一会儿,找到了一种方法,但是您需要暂时将注册表文件加载到您的注册表中并在那里进行编辑。看来您需要使用 reg.exe
来执行此操作。
另一个问题是此注册表文件中使用的自定义 属性 类型(5f5e10c
而不是 REG_BINARY
)。 PowerShell and .NET 两个 API 似乎都无法加载或正确保存它们。我不得不导出密钥,在 .reg
文件中编辑它们,然后将它们导入回来。
另一个需要考虑的特性是所有编码值中包含的时间戳,如 this blog post 中所述。
这是我设法写的一个工作脚本,在评论中有额外的解释(你需要 运行 它作为管理员,否则加载注册表文件将失败):
# full path to the registry file to edit
$settingsFile = "c:\Users\Damir\AppData\Local\Packages3f4f59-2aa3-455b-8531-185f633c1ffe_ecet6zh215f6e\Settings\settings.dat"
# setting name to change
$settingKey = "ServerUrl"
# new setting value
$newValue = "http://prodserver.local/esign/"
# name of temporary .reg file
$regFile = ".\settings.reg"
# temporary registry location to import registry file into
$registryImportLocation = "HKLM\_TMP"
# prefix matching the setting in the .reg file
$settingKeyPattern = """$settingKey""="
# load the settings file into registry
reg load $registryImportLocation $settingsFile
# export the settings into .reg file
reg export $registryImportLocation $regFile
$fileContents = Get-Content $regFile
$finalContents = @()
$processing = $false
Foreach ($line in $fileContents)
{
If (-Not ($processing))
{
If ($line.StartsWith($settingKeyPattern))
{
# setting key found, stop copying file contents
$processing = $true
# read key value without its name
$oldSerializedValue = $line.Replace($settingKeyPattern, "")
}
Else
{
# setting key not found yet, copy old file contents to output
$finalContents += $line
}
}
else
{
# value can span multiple lines, trim leading spaces from non-first lines
$oldSerializedValue += $line.TrimStart(" ")
}
If ($processing)
{
If ($oldSerializedValue.EndsWith("\"))
{
# trailing \ indicates non-final line with key value
$oldSerializedValue = $oldSerializedValue.TrimEnd("\")
}
Else
{
# split key type and value
$match = $oldSerializedValue -match '(.*:)(.*)'
# final 8 bytes are timestamp of the value - don't modify
$timestamp = $matches[2].Substring($matches[2].Length - 23)
# encode new value in UTF-16
$newValueInBytes = [System.Text.Encoding]::Unicode.GetBytes($newValue)
# key name and type
$newValue = $settingKeyPattern + $matches[1]
# encode byte array into required string format
Foreach ($byte in $newValueInBytes)
{
$newValue += [System.Convert]::ToString($byte, 16).PadLeft(2, "0") + ","
}
# end null character string terminator
$newValue += "00,00," + $timestamp
$finalContents += $newValue
# reenable copying of the remaining file
$processing = $false
}
}
}
# dump new file contents to file
$finalContents | Out-File $regFile
# import the changed value into registry
reg import $regFile
# onload the registry file from registry
reg unload $registryImportLocation
# delete temporary file
Remove-Item $regFile
您需要对其进行一些修改以将其包含在您的部署过程中,但它应该可以帮助您入门。
编辑: 我写了一个 accompanying blog post describing the thought process behind the answer. It provides an even more in depth explanation and links to a PowerShell function implementation 包装上面的脚本。