当 运行 作为系统用户从批处理文件获取用户 %APPDATA%
How to get to users %APPDATA% when running as system user from a batch file
正在通过 SCCM 部署应用程序。目前正在尝试部署 Wireshark,我第一次尝试创建目录,然后将首选项文件复制给用户 %APPDATA%
。首选项文件基本上会阻止应用程序检查自动更新。
我需要创建该目录的原因是它在第一次启动 Wireshark 之前不存在。
问题是执行此操作时,SCCM 正在作为系统用户进行部署,因此 %APPDATA%
转到目录 C:\Windows\System32\config\systemprofile\AppData\Roaming\
但是我想去C:\Users\SPECIFIC USER\AppData\Roaming
我正在使用批处理文件部署应用程序:
Wireshark-win64-2.4.6.exe /S
mkdir %APPDATA%\Wireshark\
xcopy preferences %APPDATA%\Wireshark
这将在我自己的机器上本地运行,但如果我 运行 在 PSEXEC 下(就像 SCCM 那样),那么它最终会在不正确的目录中。
我不熟悉在 SCCM 中创建应用程序以及使用批处理文件进行部署,因此请尽可能提供详细信息。无论如何,我感谢您的帮助!
这是一个可能对您有帮助的批处理文件。如果您没有指定用户名,它会在它找到的所有用户的 %APPDATA%
目录中创建您告诉它的目录,或者如果您指定了用户名,它只会在特定用户的 %APPDATA%
目录中创建目录。
@ECHO OFF
SETLOCAL
SETLOCAL ENABLEEXTENSIONS
SETLOCAL ENABLEDELAYEDEXPANSION
SET BAT=%~NX0
SET ROOTDIR=C:\Users
IF "%~1" == "" (
GOTO USAGE
)
SET "DIR=%~1"
SET "USER=%~2"
IF NOT "%USER%" == "" (
IF EXIST %ROOTDIR%\%USER%\AppData\Roaming\ (
IF NOT EXIST "%ROOTDIR%\%USER%\AppData\Roaming\%DIR%" (
MKDIR "%ROOTDIR%\%USER%\AppData\Roaming\%DIR%"
ECHO Created %ROOTDIR%\%USER%\AppData\Roaming\%DIR%
)
)
GOTO :EOF
)
FOR /F "DELIMS=" %%D IN ('DIR /A:D /B %ROOTDIR%') DO (
IF EXIST %ROOTDIR%\%%D\AppData\Roaming\ (
IF NOT EXIST "%ROOTDIR%\%%D\AppData\Roaming\%DIR%" (
MKDIR "%ROOTDIR%\%%D\AppData\Roaming\%DIR%"
ECHO Created %ROOTDIR%\%%D\AppData\Roaming\%DIR%
)
)
)
GOTO :EOF
:: --------------------------------------------------------------------------
:USAGE
ECHO.
ECHO A batch file that creates a directory in every user's %%APPDATA%% directory
ECHO if no username is specified or creates the directory only for the specific
ECHO user if the username is specified.
ECHO.
ECHO Usage: %BAT% ^<directory^> [username]
GOTO :EOF
已完成使用 getprofiles.cmd
回显配置文件并使用 main.cmd
使用 for 循环来处理配置文件路径。
main.cmd:
@echo off
setlocal
:: Install Wireshark.
echo Wireshark-win64-2.4.6.exe /S
:: Update Wireshark app data in user profiles.
for /f "tokens=*" %%A in ('getprofiles.cmd "\AppData\Roaming"') do (
call :skip_profile "%%~A" "\Administrator\" "\MSSQL$SQLEXPRESS\" || (
echo mkdir "%%~A\Wireshark\"
echo xcopy preferences "%%~A\Wireshark"
)
)
exit /b
:skip_profile
for %%A in (%*) do (
if not "%%~A" == "" if /i not "%%~A" == "%~1" (
echo "%~1"| findstr /i "%%~A" >nul 2>nul
if not errorlevel 1 (
echo Skip account "%~1"
exit /b 0
)
)
)
exit /b 1
getprofiles.cmd:
@echo off
setlocal
if "%~1" == "/?" goto :help
:: ProfileList key that contains profile paths.
set "ProfileListKey=HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
:: Get profiles directory path.
set "ProfilesDirectory="
for /f "tokens=1,3" %%A in (
'reg query "%ProfileListKey%" /v "ProfilesDirectory"'
) do if /i "%%~A" == "ProfilesDirectory" call set "ProfilesDirectory=%%~B"
if not defined ProfilesDirectory (
>&2 echo ProfilesDirectory is undefined
exit /b 1
)
:: Search all profile paths in profiles directory and echo existing paths appended with the 1st script argument.
for /f "delims=" %%A in (
'reg query "%ProfileListKey%"'
) do call :ProfilePath "%%~A" "%~1"
exit /b
:ProfilePath
setlocal
set "arg1=%~1"
:: Validate 1st call argument is a profile subkey.
if not defined arg1 exit /b 1
if /i "%arg1%" == "%ProfileListKey%" exit /b 1
if "%arg1:~,1%" == " " exit /b 1
:: Echo existing profile paths with defined 2nd argument appended.
for /f "tokens=1,3" %%A in (
'reg query "%arg1%" /v ProfileImagePath^|find /i "%ProfilesDirectory%"'
) do (
if "%%~A" == "ProfileImagePath" (
if exist "%%~B%~2" echo "%%~B%~2"
)
)
exit /b
:help
echo Prints profile paths from the registry that exist in the Profiles Directory.
echo 1st argument can be a path to be appended to the profile path.
echo i.e. "\AppData\Roaming" is appended to become "C:\Users\...\AppData\Roaming".
exit /b
脚本main.cmd
回显测试结果。去除回声
如果命令有效则实际使用。
注册表中的ProfileList
项存储查找路径
配置文件并具有子项,其中包含数据,例如每个配置文件的路径
机器。
main.cmd
可以避免Administrator
和MSSQL$SQLEXPRESS
等配置文件。
被调用的标签 :skip_profile
将配置文件路径作为第一个参数。
以下参数用于模式,如果匹配,将被跳过
轮廓。
findstr
用于检查配置文件路径是否与
正则表达式,因此使用 findstr /?
来满足语法要求。
对于 /i
.
的使用,大小写设置为不敏感
getprofiles.cmd
脚本获取 ProfilesDirectory
路径
是可以找到用户配置文件文件夹的地方。然后它查询密钥
使用 :ProfilePath
的调用标签获取配置文件密钥。
标签检查是否在每个文件中找到 ProfilesDirectory
路径
找到配置文件路径。然后在回显之前检查路径是否存在
路径。如果传递了可选的第一个参数,那么它将是
追加,路径将被验证为该路径。
一个测试输出:
Wireshark-win64-2.4.6.exe /S
mkdir "C:\Users\Michael\AppData\Roaming\Wireshark\"
xcopy preferences "C:\Users\Michael\AppData\Roaming\Wireshark"
这似乎没问题,因为我当前的计算机上只有 1 个用户配置文件。
不过,您可能可以将代码合并在一起,只制作 1 个脚本
我决定将 getprofiles.cmd
保留为可重复用于其他用途。
查找 EXPLORER.EXE 进程的所有者:
for /f "TOKENS=1,2,*" %%a in ('tasklist /FI "IMAGENAME eq explorer.exe" /FO LIST /V') do if /i "%%a %%b"=="User Name:" (set domain_user=%%c)
for /f "TOKENS=1,2 DELIMS=\" %%a in ("%domain_user%") do set domain=%%a && set LoggedInUserID=%%b
for /f "TOKENS=1,2,*" %%a in ('tasklist /FI "IMAGENAME eq explorer.exe" /FO LIST /V') do if /i "%%a %%b"=="User Name:" (set domain_user=%%c)
for /f "TOKENS=1,2 DELIMS=" %%a in ("%domain_user%") do set domain=%%a && set LoggedInUserID=%%b
正在通过 SCCM 部署应用程序。目前正在尝试部署 Wireshark,我第一次尝试创建目录,然后将首选项文件复制给用户 %APPDATA%
。首选项文件基本上会阻止应用程序检查自动更新。
我需要创建该目录的原因是它在第一次启动 Wireshark 之前不存在。
问题是执行此操作时,SCCM 正在作为系统用户进行部署,因此 %APPDATA%
转到目录 C:\Windows\System32\config\systemprofile\AppData\Roaming\
但是我想去C:\Users\SPECIFIC USER\AppData\Roaming
我正在使用批处理文件部署应用程序:
Wireshark-win64-2.4.6.exe /S
mkdir %APPDATA%\Wireshark\
xcopy preferences %APPDATA%\Wireshark
这将在我自己的机器上本地运行,但如果我 运行 在 PSEXEC 下(就像 SCCM 那样),那么它最终会在不正确的目录中。
我不熟悉在 SCCM 中创建应用程序以及使用批处理文件进行部署,因此请尽可能提供详细信息。无论如何,我感谢您的帮助!
这是一个可能对您有帮助的批处理文件。如果您没有指定用户名,它会在它找到的所有用户的 %APPDATA%
目录中创建您告诉它的目录,或者如果您指定了用户名,它只会在特定用户的 %APPDATA%
目录中创建目录。
@ECHO OFF
SETLOCAL
SETLOCAL ENABLEEXTENSIONS
SETLOCAL ENABLEDELAYEDEXPANSION
SET BAT=%~NX0
SET ROOTDIR=C:\Users
IF "%~1" == "" (
GOTO USAGE
)
SET "DIR=%~1"
SET "USER=%~2"
IF NOT "%USER%" == "" (
IF EXIST %ROOTDIR%\%USER%\AppData\Roaming\ (
IF NOT EXIST "%ROOTDIR%\%USER%\AppData\Roaming\%DIR%" (
MKDIR "%ROOTDIR%\%USER%\AppData\Roaming\%DIR%"
ECHO Created %ROOTDIR%\%USER%\AppData\Roaming\%DIR%
)
)
GOTO :EOF
)
FOR /F "DELIMS=" %%D IN ('DIR /A:D /B %ROOTDIR%') DO (
IF EXIST %ROOTDIR%\%%D\AppData\Roaming\ (
IF NOT EXIST "%ROOTDIR%\%%D\AppData\Roaming\%DIR%" (
MKDIR "%ROOTDIR%\%%D\AppData\Roaming\%DIR%"
ECHO Created %ROOTDIR%\%%D\AppData\Roaming\%DIR%
)
)
)
GOTO :EOF
:: --------------------------------------------------------------------------
:USAGE
ECHO.
ECHO A batch file that creates a directory in every user's %%APPDATA%% directory
ECHO if no username is specified or creates the directory only for the specific
ECHO user if the username is specified.
ECHO.
ECHO Usage: %BAT% ^<directory^> [username]
GOTO :EOF
已完成使用 getprofiles.cmd
回显配置文件并使用 main.cmd
使用 for 循环来处理配置文件路径。
main.cmd:
@echo off
setlocal
:: Install Wireshark.
echo Wireshark-win64-2.4.6.exe /S
:: Update Wireshark app data in user profiles.
for /f "tokens=*" %%A in ('getprofiles.cmd "\AppData\Roaming"') do (
call :skip_profile "%%~A" "\Administrator\" "\MSSQL$SQLEXPRESS\" || (
echo mkdir "%%~A\Wireshark\"
echo xcopy preferences "%%~A\Wireshark"
)
)
exit /b
:skip_profile
for %%A in (%*) do (
if not "%%~A" == "" if /i not "%%~A" == "%~1" (
echo "%~1"| findstr /i "%%~A" >nul 2>nul
if not errorlevel 1 (
echo Skip account "%~1"
exit /b 0
)
)
)
exit /b 1
getprofiles.cmd:
@echo off
setlocal
if "%~1" == "/?" goto :help
:: ProfileList key that contains profile paths.
set "ProfileListKey=HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
:: Get profiles directory path.
set "ProfilesDirectory="
for /f "tokens=1,3" %%A in (
'reg query "%ProfileListKey%" /v "ProfilesDirectory"'
) do if /i "%%~A" == "ProfilesDirectory" call set "ProfilesDirectory=%%~B"
if not defined ProfilesDirectory (
>&2 echo ProfilesDirectory is undefined
exit /b 1
)
:: Search all profile paths in profiles directory and echo existing paths appended with the 1st script argument.
for /f "delims=" %%A in (
'reg query "%ProfileListKey%"'
) do call :ProfilePath "%%~A" "%~1"
exit /b
:ProfilePath
setlocal
set "arg1=%~1"
:: Validate 1st call argument is a profile subkey.
if not defined arg1 exit /b 1
if /i "%arg1%" == "%ProfileListKey%" exit /b 1
if "%arg1:~,1%" == " " exit /b 1
:: Echo existing profile paths with defined 2nd argument appended.
for /f "tokens=1,3" %%A in (
'reg query "%arg1%" /v ProfileImagePath^|find /i "%ProfilesDirectory%"'
) do (
if "%%~A" == "ProfileImagePath" (
if exist "%%~B%~2" echo "%%~B%~2"
)
)
exit /b
:help
echo Prints profile paths from the registry that exist in the Profiles Directory.
echo 1st argument can be a path to be appended to the profile path.
echo i.e. "\AppData\Roaming" is appended to become "C:\Users\...\AppData\Roaming".
exit /b
脚本main.cmd
回显测试结果。去除回声
如果命令有效则实际使用。
注册表中的ProfileList
项存储查找路径
配置文件并具有子项,其中包含数据,例如每个配置文件的路径
机器。
main.cmd
可以避免Administrator
和MSSQL$SQLEXPRESS
等配置文件。
被调用的标签 :skip_profile
将配置文件路径作为第一个参数。
以下参数用于模式,如果匹配,将被跳过
轮廓。
findstr
用于检查配置文件路径是否与
正则表达式,因此使用 findstr /?
来满足语法要求。
对于 /i
.
getprofiles.cmd
脚本获取 ProfilesDirectory
路径
是可以找到用户配置文件文件夹的地方。然后它查询密钥
使用 :ProfilePath
的调用标签获取配置文件密钥。
标签检查是否在每个文件中找到 ProfilesDirectory
路径
找到配置文件路径。然后在回显之前检查路径是否存在
路径。如果传递了可选的第一个参数,那么它将是
追加,路径将被验证为该路径。
一个测试输出:
Wireshark-win64-2.4.6.exe /S
mkdir "C:\Users\Michael\AppData\Roaming\Wireshark\"
xcopy preferences "C:\Users\Michael\AppData\Roaming\Wireshark"
这似乎没问题,因为我当前的计算机上只有 1 个用户配置文件。
不过,您可能可以将代码合并在一起,只制作 1 个脚本
我决定将 getprofiles.cmd
保留为可重复用于其他用途。
查找 EXPLORER.EXE 进程的所有者:
for /f "TOKENS=1,2,*" %%a in ('tasklist /FI "IMAGENAME eq explorer.exe" /FO LIST /V') do if /i "%%a %%b"=="User Name:" (set domain_user=%%c)
for /f "TOKENS=1,2 DELIMS=\" %%a in ("%domain_user%") do set domain=%%a && set LoggedInUserID=%%b
for /f "TOKENS=1,2,*" %%a in ('tasklist /FI "IMAGENAME eq explorer.exe" /FO LIST /V') do if /i "%%a %%b"=="User Name:" (set domain_user=%%c)
for /f "TOKENS=1,2 DELIMS=" %%a in ("%domain_user%") do set domain=%%a && set LoggedInUserID=%%b