我的Azure Web角色需要能够删除存储在App_Data子文件夹中的临时本地文件。我想在Azure提升的启动任务中使用ICACLS,以允许IIS按如下方式执行此操作:
ICACLS App_Data / grant“IIS_IUSRS”:( OI)(CI)F
但是,我的启动任务在以下位置执行:
E:\为approot \ BIN
而Web应用程序实际结束并执行的根文件夹似乎是:
E:\ sitesroot \ 0
如果微软改变了这一点,我不愿意对此路径进行硬编码。有没有办法从启动任务中获取此路径,还是可以依赖此目的地?
要在ASPX中对此进行测试,我添加:
Label1.Text = "MapPath: " + Server.MapPath("~/");
Label2.Text = "RoleRoot: " + Environment.GetEnvironmentVariable("RoleRoot");
当我在部署的实例上运行它时,我得到:
MapPath:E:\ sitesroot \ 0 \ RoleRoot:
即。 RoleRoot为空。
那我怎样才能得到Server.MapPath(“〜/”)的结果;在启动任务中?
答案 0 :(得分:3)
为什么不相对?部署 sitesroot 和 approot 的驱动器似乎在E:\和F:\之间切换,但我认为现在假设它们将被部署是更安全的选择作为兄弟文件夹。
这是我们从siteroot文件夹中复制文件的启动任务:
xcopy "../../sitesroot/0/bin" "../../sitesroot/1/bin" /y /i /S
xcopy "../../sitesroot/0/bin" "../../sitesroot/2/bin" /y /i /S
xcopy "../../sitesroot/0/bin" "../../sitesroot/3/bin" /y /i /S
xcopy "../../sitesroot/0/bin" "../../sitesroot/4/bin" /y /i /S
xcopy "../../sitesroot/0/bin" "../../sitesroot/5/bin" /y /i /S
答案 1 :(得分:3)
不使用命令提示符中的icacls,而是使用Powershell脚本,因为Powershell允许您枚举IIS中的网站并获取物理文件夹路径。
不幸的是,您无法将Powershell脚本设置为启动任务。因此,您必须创建常规CMD或BAT文件,然后在此文件中请求Powershell执行您的脚本。
CMD文件:
PowerShell -ExecutionPolicy Unrestricted .\Setup.ps1 >> %TEMP%\Setup-DebugLog.txt 2>&1
exit /B 0
第一行执行Powershell脚本并将所有输出保存到文件Setup-DebugLog.txt。第二行确保CMD文件向Windows Azure返回OK,因此Azure知道启动脚本中的一切都很顺利。
以下是我用于在App_Data文件夹上设置文件夹权限的Powershell脚本:
Import-Module WebAdministration
cd IIS:\Sites
$dir = Get-ChildItem
$timeout = 0
while ($dir -eq $NULL -and $timeout -lt 11)
{
"IIS Site not ready. Waiting for 2 seconds..."
[System.Threading.Thread]::Sleep(2000)
$timeout++
$dir = Get-ChildItem
}
if ($dir -eq $NULL)
{
"IIS Site still not ready. Aborting."
}
else
{
"IIS site ready."
Set-Location $dir.physicalPath
"Location is $($dir.physicalPath)"
$acl = (Get-Item App_Data).GetAccessControl("Access")
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("Network Service", "Modify, Write", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
Set-Acl App_Data $acl
"Permission added."
}
首先导入WebAdministration模块,该模块允许Powershell与IIS交互。然后它尝试枚举网站。但是,这是一个有趣的挑战。因为,在将网站部署到IIS之前运行启动任务。因此,您需要将启动任务设置为作为后台任务运行,然后等待该站点部署完毕。所以代码试图枚举网站,如果没有找到网站,它会等待2秒然后再次尝试。它总共持续20秒,然后超时。 如果网站已准备就绪,则会找到物理路径,并将FileSystemAccessRule添加到App_Data文件夹的ACL中。您可以修改添加的权限以满足您的需求。 请注意,此脚本预计IIS中只有一个站点。如果您部署了多个网站,则此脚本可能无法运行,您必须调整代码。
为了完整性,以下是您应添加到ServiceDefinition.csdef
的<:p>的XML
<Startup>
<Task commandLine="Setup.cmd" executionContext="elevated" taskType="background" />
</Startup>
Setup.cmd
和Setup.ps1
都应放在您网站的根目录中。如果您希望将它们放在网站的子文件夹中,您可以这样做,但是您必须将Task元素中的commandLine属性更新为“Subfolder \ Setup.cmd”,并且您需要更新CMD文件中Powershell文件的路径:
PowerShell -ExecutionPolicy Unrestricted .\Subfolder\Setup.ps1 >> %TEMP%\Setup-DebugLog.txt 2>&1
另请注意,在Powershell v1和v2之间调用Powershell脚本存在一些差异。如果我没记错的话,Windows Azure上的Windows 2008运行Powershell v1,Windows 2008 R2和更新版本运行Powershell v2。因此,如果您在Azure上使用Windows 2008,则需要更改调用Powershell脚本的行,因为在设置执行策略时存在一些差异。
答案 2 :(得分:2)
有一个名为%ROLEROOT%的环境变量可以获取应用程序的路径。
string appRoot = Environment.GetEnvironmentVariable("RoleRoot");
appRoot = Path.Combine(appRoot + @"\", @"approot\");
详细了解此here。
答案 3 :(得分:1)
不,我不认为启动任务可以通过网络角色获取您网站的根目录。