我有一个 powershell 脚本,当我使用以下命令从命令提示符手动执行它时,它可以完美运行:
powershell -NoLogo -NonInteractive -File "D:\ServerFolders\Company\Scripts\Powershell Scripts\SendMonthlyGrowthRateReport.ps1"
脚本打开一个 excel 电子表格,将一些数据从 SQL 提取到电子表格中,保存一份包含当前日期的电子表格副本,然后通过 SQL sp_send_dbmail 将电子表格通过电子邮件发送出去。它还将当前状态记录到日志文件中。
现在我在 Windows 2012 R2 上设置了一个计划任务,每月执行一次上述命令,但是当我手动运行该任务或尝试让它自行启动时,只会生成日志文件,而不会生成电子表格已保存,电子邮件永远不会消失。
有什么想法吗?
更新: 下面是脚本中的代码,我还应该注意 powershell 在通过计划任务执行时返回退出代码 0...
$DebugPreference = 2
$VerbosePreference = 2
$WarningPreference = 2
#param([string] $TemplateFilePath = "TemplateFilePath",
# [string]$StorageRoot = "StorageRoot",
# [string]$NameFormat = "NameFormat",
# [string]$ReportType = "ReportType",
# [string] $SendReportTo = "SendReportTo")
$TemplateFilePath = 'D:\ServerFolders\Company\Spreadsheets\templates\DatabaseGrowthTemplate.xlsx'
$StorageRoot = 'D:\ServerFolders\Company\Spreadsheets'
$NameFormat = '%type% Database Growth Report %date%.xlsx'
$ReportType = "Monthly"
$SendReportTo ="*******@someDomain.com"
$Date = get-Date
$LogFile = "D:\ServerFolders\Company\SyncLogs\MonthlyGrowthReport" + $Date.toString("yyyy-MM-dd hhmmss") + ".log"
Function LogWrite
{
Param ([string]$logstring)
$date = get-date
$DateString = $date.toString("yyyy-MM-dd hh:mm:ss")
$FileValue = $DateString +' - ' + $logstring
if($LogFile -ne $null -and $LogFile -ne "")
{
Add-content $Logfile -value $FileValue
}
Write-Host $FileValue
}
if ($ReportType -ne 'Weekly' -and $ReportType -ne 'Monthly' -and $ReportType -ne 'Quarterly' -and $ReportType -ne 'Yearly')
{
Write-Host "Valid options for ReportType parameter are 'Weekly', 'Monthly', 'Quarterly', or 'Yearly'"
exit
}
$Date = get-Date
$DateString = $Date.ToString("yyyy-MM-dd")
$FromDate = $DateString
$FileName = $NameFormat.Replace("%date%", $DateString)
$FileName = $FileName.Replace("%type%", $ReportType)
$Destination = join-path $StorageRoot $FileName
$LogWrite = "Generate Destination File of " + $Destination
LogWrite $LogWrite
$IncrementType ="Days"
if ($ReportType -eq "Weekly"){
$IncrementType = "Weeks"
}
if ($ReportType -eq "Monthly"){
$IncrementType = "Months"
}
if ($ReportType -eq "Quarterly"){
$IncrementType = "Quarters"
}
if ($ReportType -eq "Yearly") {
$IncrementType = "Years"
}
$IncrementBackValue = -1
## Connect to the target SQL Server and run the query to refresh data
$cstr = "Server=SERVERNAME\INSTANCENAME;Database=Logging;Trusted_Connection=True;"
$cn = new-object system.data.SqlClient.SqlConnection($cstr);
LogWrite "Connecting to SQL"
$cn.Open()
#Query the first date from using the built-in function
$dateQuery = "SELECT [dbo].[ufn_getIncrementBackDate]('$DateString', '${IncrementType}', ${IncrementBackValue}) as [StartDate]"
$cmd1 = New-Object System.Data.SqlClient.SqlCommand($dateQuery, $cn)
$DateDS = $cmd1.ExecuteReader();
while($DateDS.Read()){
$StartDate = $DateDS.GetDateTime(0)
}
$DateDS.Close()
#Copy isn't needed Open the template and then at the End do a save as
LogWrite "Opening Excel workbook..."
# Open the Excel document and pull in the 'Data' worksheet
$Excel = New-Object -Com Excel.Application
$Workbook = $Excel.Workbooks.Open($TemplateFilePath)
$page = 'Data'
$ws = $Workbook.worksheets | where-object {$_.Name -eq $page}
# Delete the current contents of the page
$ws.Cells.Clear() | Out-Null
LogWrite "Generating Report Data..."
#Prepare adapter objects for reading info into Excel
$ds = new-object "System.Data.DataSet" "dsProductData"
$q = "usp_GenerateDatabaseSizeReport @FirstDate='$StartDate'"
$da = new-object "System.Data.SqlClient.SqlDataAdapter" ($q, $cn)
$da.Fill($ds) | Out-Null
$dtProduct = $ds.Tables[0]
# Set variables for the worksheet cells, and for navigation
$cells=$ws.Cells
$row=1
$col=1
$MaxCol = 1
$MaxRow = 1
LogWrite "Populating Data worksheet.."
#Fill Headers
foreach($column in $dtProduct.Columns){
$cells.item($row, $col) = $column.ColumnName
if ($col -gt $MaxCol){
$MaxCol = $col
}
$col++
}
# Add the results from the DataTable object to the worksheet
foreach($dataRow in $dtProduct){
$row++
$col = 1
foreach($column in $dtProduct.Columns)
{
if ($col -eq 1){
$cells.item($row, $col) = $dataRow[$column.ColumnName].ToString()
} else {
$cells.item($row, $col) = $dataRow[$column.ColumnName].ToString()
}
$col++
}
if ($row -gt $MaxRow){
$MaxRow = $row
}
}
LogWrite "Finished populating Data..."
# Set the width of the columns automatically
$ws.columns.item("A:Z").EntireColumn.AutoFit() | out-null
#Format Date Column
$ws.Range("A2:A1000").NumberFormat ="m/d/yyyy"
#Create the Line Chart's
$ColumnLetter = "A"
if ($MaxCol -eq 1) { $ColumnLetter = "A" }
if ($MaxCol -eq 2) { $ColumnLetter = "B" }
if ($MaxCol -eq 3) { $ColumnLetter = "C" }
if ($MaxCol -eq 4) { $ColumnLetter = "D" }
if ($MaxCol -eq 5) { $ColumnLetter = "E" }
if ($MaxCol -eq 6) { $ColumnLetter = "F" }
if ($MaxCol -eq 7) { $ColumnLetter = "G" }
if ($MaxCol -eq 8) { $ColumnLetter = "H" }
if ($MaxCol -eq 9) { $ColumnLetter = "I" }
if ($MaxCol -eq 10) { $ColumnLetter = "J" }
if ($MaxCol -eq 11) { $ColumnLetter = "K" }
if ($MaxCol -eq 12) { $ColumnLetter = "L" }
if ($MaxCol -eq 13) { $ColumnLetter = "M" }
if ($MaxCol -eq 14) { $ColumnLetter = "N" }
if ($MaxCol -eq 15) { $ColumnLetter = "O" }
if ($MaxCol -eq 16) { $ColumnLetter = "P" }
if ($MaxCol -eq 17) { $ColumnLetter = "Q" }
if ($MaxCol -eq 18) { $ColumnLetter = "R" }
if ($MaxCol -eq 19) { $ColumnLetter = "S" }
if ($MaxCol -eq 20) { $ColumnLetter = "T" }
if ($MaxCol -eq 21) { $ColumnLetter = "U" }
if ($MaxCol -eq 22) { $ColumnLetter = "V" }
if ($MaxCol -eq 23) { $ColumnLetter = "W" }
if ($MaxCol -eq 24) { $ColumnLetter = "X" }
if ($MaxCol -eq 25) { $ColumnLetter = "Y" }
if ($MaxCol -eq 26) { $ColumnLetter = "Z" }
$RangeString = "A1:"+$ColumnLetter
#$RangeString
$RangeString =$RangeString + $MaxRow
#$RangeString
$range = $ws.range($RangeString)
LogWrite "Performing Chart updates."
$page = "Chart"
$ws = $Workbook.worksheets | where-object {$_.Name -eq $page}
foreach($Shape in $ws.Shapes){
if ($Shape.HasChart){
$chart = $Shape.Chart
break
}
if ($chart -ieq $null){
Write-Host "Can't find chart!!!"
} else {
$chart.SetSourceData($range)
}
LogWrite "Saving updated copy of Excel workbook."
# Close the workbook and exit Excel
$Workbook.SaveAs($Destination)
$workbook.Close($true)
$excel.quit()
$DestinationFileO = New-Object System.IO.FileInfo($Destination)
$EmailSubject = $DestinationFileO.Name.Replace($DestinationFileO.Extension, "")
LogWrite "Sending Excel Workbook via email."
#Send an email to operator with report
$SendEmailCmdText ="exec msdb..sp_send_dbmail @profile_name='GMail'
, @recipients = '${SendReportTo}'
, @subject = '${EmailSubject}'
, @body = 'Attached is the $EmailSubject for database server [HOMEGROWNSERVER\TFSSQL].'
, @file_attachments = '${Destination}'
--, @query_result_header = 1
--, @query_result_separator=','
--, @query_result_width = 32767
--, @append_query_error = 1
--, @query_result_no_padding = 1"
$cmd2 = New-Object System.Data.SqlClient.SqlCommand($SendEmailCmdText, $cn)
$cmd2.ExecuteNonQuery()
$cn.Close()
LogWrite "Process Complete"
最佳答案
您最有可能的问题是打开 Excel 需要交互式 session 。
$Excel = New-Object -Com Excel.Application
$Workbook = $Excel.Workbooks.Open($TemplateFilePath)
当您将脚本作为计划作业运行时,这些行将失败。据我所知;在 Windows 2012 R2 中;让它工作的唯一方法是将计划的作业设置为“仅在用户登录时运行”并让用户保持登录状态。
很抱歉没有回答,但我还没有找到解决方法。
关于windows - 通过计划任务的 PowerShell 脚本不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28965403/
我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时
我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub
我正在使用puppet为ruby程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这
如何使用RSpec::Core::RakeTask初始化RSpecRake任务?require'rspec/core/rake_task'RSpec::Core::RakeTask.newdo|t|#whatdoIputinhere?endInitialize函数记录在http://rubydoc.info/github/rspec/rspec-core/RSpec/Core/RakeTask#initialize-instance_method没有很好的记录;它只是说:-(RakeTask)initialize(*args,&task_block)AnewinstanceofRake
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
我有一个在Linux服务器上运行的ruby脚本。它不使用rails或任何东西。它基本上是一个命令行ruby脚本,可以像这样传递参数:./ruby_script.rbarg1arg2如何将参数抽象到配置文件(例如yaml文件或其他文件)中?您能否举例说明如何做到这一点?提前谢谢你。 最佳答案 首先,您可以运行一个写入YAML配置文件的独立脚本:require"yaml"File.write("path_to_yaml_file",[arg1,arg2].to_yaml)然后,在您的应用中阅读它:require"yaml"arg
我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象