Powershell Exceptions/Registry Key - sql-server

I have a script - with its according module - that lists from SQL all the instances from different Servers within the company I'm interning for.
This script works in another host machine but not in mine.
I get a MethodInvocationException and the error message is the following:
Exception calling "OpenSubKey" with "1" argument(s): "Requested registry access is not allowed."
The error comes from a file inside a module, not from the actual script.
I know its very general and Im not allowed to show the code, but any guidlines/tips or heads up on how to solve it? I tried playing around with something called registry key, but I'm not sure how it works.
Help please?

You can use Process Monitor to view all the registry accesses. This will show the one for which access is denied, and from there you can grant yourself the necessary access.
You will need to set suitable filters or you will be overwhelmed by the number of events! I would suggest the following:
Path: Operation is "RegOpenKey"
Result: is "Access Denied"
Option 2
Execute the command in PowerShell, then execute the following command:
$> $Error[0]
This should hopefully print something like the following, which will tell you the key it failed on:
dir : Requested registry access is not allowed.
At line:1 char:1
+ dir
+ ~~~
+ CategoryInfo : PermissionDenied: (HKEY_LOCAL_MACHINE\SECURITY:String) [Get-ChildItem], SecurityException
+ FullyQualifiedErrorId : System.Security.SecurityException,Microsoft.PowerShell.Commands.GetChildItemCommand

Related

Running Powershell Script from SQL Server Agent

How different should the programming be when you execute a powershell script from SQL Server Agent. I have been seeing very weird behavior.
Any object call fails
Can't we use powershell functions in these scripts. The parameters go empty if we call function through an object parameter
Some commands just don't pring messages, even though I use a variable hard print or I use Write-Output.
I just wanted to know why this is too different. I have a big script that automated and helped big manual task, which works with no errors at all when done manually.
Please help me on this.
Object: $agobj = $PrimarySQLConnObj.AvailabilityGroups[$AGName]
Error from Agent History:
The corresponding line is ' Add-SqlAvailabilityDatabase -InputObject $agobj -Database "$db" -ErrorAction Stop '. Correct the script and reschedule the job. The error information returned by PowerShell is: 'Cannot bind parameter 'InputObject'. Cannot convert the "[AG]" value of type "Microsoft.SqlServer.Management.Smo.AvailabilityGroup" to type "Microsoft.SqlServer.Management.Smo.AvailabilityGroup"

Deploying SQL Changes Containing $(ESCAPE_SQUOTE())

I have a Database project in Visual Studio that I am attempting to deploy automatically to a test environment nightly. To accomplish this I am using TFS which leverages a PowerShell script to run "SqlPackage.exe" to deploy any changes that have occurred during the day.
Some of my procs contain logic that is run inside of a script that is part of a agent job step and contains the following code(In dynamic SQL):
$(ESCAPE_SQUOTE(JOBID))
When deploying changes that affect this proc, I get the following issue:
SQL Execution error: A fatal error occurred. Incorrect syntax was
encountered while $(ESCAPE_SQUOTE( was being parsed.
This is a known issue, it appears as though that is not supported. It appears to be a function of the "SQLCmd" command misinterpreting the $( characters as a variable:
"override the value of a SQL command (sqlcmd) variable used during a
publish action."
So how do I get around this? It seems to be a major limitation of "sqlcmd" that you can't disable variables, I don't see that parameter that supports that...
Update 1
Seems as through you can disable variable substitution from "sqlcmd" by feeding it the "-x" argument(Source, Documentation):
-x (disable variable substitution)
Still don't see a way to do this from "SqlPackage.exe" though.
It seems that sqlcmd looks for the $( as a token, so separating those two characters is good enough. You can do this with a dynamic query that does nothing more than break the query into two strings:
DECLARE #query nvarchar(256) = N'... $' + N'(ESCAPE_SQUOTE(JOBID)) ...';
EXEC sp_executesql #query
One way to get around this is to refactor the "$(ESCAPE_SQUOTE(JOBID))" string into a scalar function, then setup a PowerShell script to directly invoke the "Sqlcmd" command with the "-x" parameter to "Create/Alter" said function before running "SqlPackage.exe".
Looks something like this in PowerShell:
$sql = #"
USE $database
GO
CREATE FUNCTION [dbo].[GetJobID] ()
RETURNS NVARCHAR(MAX)
AS
BEGIN
RETURN '$(ESCAPE_SQUOTE(JOBID))'
END
GO
"#;
Sqlcmd -S $servername -U $username -P $password -Q $sql -x;
This is a pretty poor workaround, but it does accomplish the task. Really hoping for something better.
I propose another workaround
my job has a step running : DTEXEC.exe /SERVER "$(ESCAPE_NONE(SRVR))"
I just have to add a SQLCMD variable before:
:setvar SRVR "$(ESCAPE_NONE(SRVR))"
this way the toked is considered as SQLCMD variables $(SRVR) and is replaced by the requested value

TFS Build providing prebuild auto increment assembly information by 1 and post publish zip the files

I am trying to implement Build automation using TFS (Version 12.0.31101.0)
This is the settings I am using, It build properly and publishes to the mentioned drop location:
For PreBuild I am trying to use the following batch script and this is not incrementing:
$path = "E:\Dev\ABC\My Project\AssemblyInfo.vb"
$pattern = '\<Assembly: AssemblyVersion\(.*\)\>'
(Get-Content $path) | ForEach-Object{
if($_ -match $pattern){
# We have found the matching line
# Edit the version number and put back.
$fileVersion = [version]$matches[1]
Write-Output "Major is $Matches[0] Minor is $Matches[1] Build is $Matches[2] Revision is [version]$matches[3]"
$newVersion = "{0}.{1}.{2}.{3}" -f $fileVersion.Major, $fileVersion.Minor, $fileVersion.Build, ($fileVersion.Revision + 1)
'<Assembly: AssemblyVersion("{0}")>' -f $newVersion
} else {
# Output line as is
$_
}
} | Set-Content $path
For 'post build script path' i want to zip the contents and put it into another folder, I am using the following script for this.
powershell.exe -nologo -noprofile -command "& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::CreateFromDirectory('\$(TF_BUILD_DROPLOCATION)\MySolution\_PublishedWebsites\ABC', 'ABC_Deploy.zip'); }"
On Executon it throws the following error:
Exception calling "CreateFromDirectory" with "2" argument(s): "Could not find
a part of the path 'C:\$TF_BUILD_DROPLOCATION\MySolution\_PublishedWebsites\ABC
At line:1 char:53
+ & { Add-Type -A 'System.IO.Compression.FileSystem';
[IO.Compression.ZipFile]::Cr ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DirectoryNotFoundException
What changes should i make for both prebuild script and post build script to get this working?
For Prebuild:
Create a C# project(i used console project) which updates the assembly information..
Add RunScript to TFS build template before MSBuild.
Call the exe which is generated from c# project from your batch file, and pass the parameter as where your source code location.
Eg: (START "C:\UpdateAssemblyTest.exe" "\TFS-Server\TFSMapPath\ABC\")
PostBuild: I found a workaround for getting the TF_BUILD_DROPLOCATION. I modified the TFS Build Template and added a 'RunScript' tool and called my batch file from there and passed the drop location as an argument.
For 'Post Build Script' If build drop location is not accessible via the variable you are using; try using COPY command and copy the dropped folders to a known location on TFS Build server and then give that path in the ZIP Powershell command. (Though it is workaround for now. :) )
For 'Pre build Script', I will check and come back to you.
For 'post build script path', according to the Exception message it cannot identify the variable $TF_BUILD_DROPLOCATION.
As it's environment variable, So,please try to access the variables using $env:. The drop location would be
$env:TF_BUILD_DROPLOCATION for example.
For PreBuild, if you want to version the assemblies, you can try to put all custom Versioning work into a custom Version.proj MsBuild script and call it in TFS build definition before the .sln. The script injects Version into source code (SharedAssemblyInfo.cs, Wix code, readme.txt), and then solution build builds that source code. Please reference this thread :Versioning .NET builds
You can also reference this article :
https://www.stevefenton.co.uk/2012/11/automatically-updating-your-assemblyinfo-with-a-batch-file/

Powershell returns negative exit code while script results are correct

I have made the following PowerShell script:
Set-Location D:\folder1\folder2\folder3\folder4;
Get-ChildItem | Rename-Item -NewName {$_.BaseName.insert(19,'loadtime') + (Get-Date -Format HHmm) + $_.Extension};
The goal is to rename a file by adding loadtime at position 19 and a time stamp. While the results of running the scripts the following error message is returned:
Rename-Item : The input to the script block for parameter 'NewName' failed.
Exception calling "Insert" with "2" argument(s): "Specified argument was out
of the range of valid values.
Parameter name: startIndex"
At D:\folder1\folder2\folder3\folder4\folder5\RenameFile.ps1:2
char:38
+ Get-ChildItem | Rename-Item -NewName {$_.BaseName.insert(19,'loadtime') +
(Get-D ...
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (Archive:PSObject) [Rename-
Item], ParameterBindingException
+ FullyQualifiedErrorId :
ScriptBlockArgumentInvocationFailed,
Microsoft.PowerShell.Commands.RenameItemCommand
When I run the script from my SSIS package I get the following error:
[Execute Process Task] Error: In Executing "PowerShell.exe" "-F D:\folder1\folder2\folder3\folder4\folder5\exec RenameFile.ps1" at "", The process exit code was "-196608" while the expected was "0".
I have tried to search for this error message but I could not find a page talking about this specific exit code.
The problem is though that while running the script commands from a PowerShell window I would still get the error message but the filename does change as expected. However since an error is returned the Execute Process Task in SSIS will fail.
My question is, what is the cause of this error? I assume it has to do with:
{$_.BaseName.insert(19,'loadtime') + (Get-Date -Format HHmm) + $_.Extension};
Wherein $.BaseName.insert(19,'loadtime') and (Get-Date -Format HHmm) and + $.Extension are seen as separate arguments.
My knowledge of PowerShell is not too great so this is just speculation on my part.
What would help me get rid of the error?
Thanks in advance!
As per the comments, the issue was caused by trying to insert into non-existing part of a string. This will raise an exception.
As a solution, make sure the indexed location exists, or just concatenate at the end. Like so,
$_.basename + 'loadtime' + (get-date -format hhMM) + $_.extension
The weird error code -196608 is actually a result of an error code represented as decimal (base 10) integer instead of hex value (base 16). Consider this:
[int]$i = -196608
$i.ToString('x')
fffd0000
What happens here is that the real error code is, in hex format, 0xFFFD0000. Because of Two's Compliment, large enough hex values actually represent negative decimal numbers.
As for this particular error code, it pops up every here and there without proper documentation. Should I hazard a guess, it has something to do with the fact that Powershell itself works fine, but the script it was told to run didn't.

has anyone faced this error "Error: No valid counters" using type perf?

Has anyone faced this error, Error: No valid counters, using typeperf utility while writing it to SQL database. I have tried variety of different things but every time I try to write it in SQL database using counters in a file it fails with the No valid counters error.
The command was executed in the following fashion:
C:\>typeperf -cf "E:\DBA\CounterCollector\counters_eg.txt" -si 15 -sc 10 -f SQL -o SQL:SQLServerDS!log5
The counters_eg.txt file contains:
"\\<computername>\PhysicalDisk(* *)\Avg. Disk Queue Length"
I am able to write in SQL database by specifying the counters individually at command prompt.
example:
C:\Windows\system32>typeperf -f SQL -o SQL:SQLServerDS!log4 "\\<computername>\PhysicalDisk(* *)\Avg. Disk Queue Length"
Note: I have replaced the server name by <computername>.
Include a double '%%', i.e.
typeperf "\\<remote-IP>\Process(*)\%% Processor Time" -sc 1
Figured it out:
After following the example from
https://www.simple-talk.com/sql/performance/collecting-performance-data-into-a-sql-server-table/
I kept on getting the same error message "Error: No valid counters". The counter.txt is exactly the same like the example provided by Feodor but when I put the counter names on the command line individually, they get processed successfully. The problem I was getting was when I tried to run the entire syntax.
Instead of using what Feodor used:
"TYPEPERF -f SQL -s ALF -cf “C:\CounterCollect\Counters.txt” -si 15 -o SQL:SQLServerDS!log1 -sc 4",
I tweaked it a little bit (after looking at the second example from http://technet.microsoft.com/en-us/library/cc753182.aspx) and finally it WORKED! It is a matter of switching the parameters.
After following the demo by Feodor, I used this below syntax, and it worked for me. I am using SQL Server 2012 and here is the command:
TYPEPERF -cf "C:\PerfMonCollect\Counters.txt" -si 5 -sc 4 -f SQL -o SQL:SQLdatasource!log1".
Your counters list may be damaged. Run perfmon GUI utility and make sure that you are able to see the counters in there.
make sure your file name is correct. counters.txt NOT counters.txt.txt . show extensions then check the file name. also, you can try the RUN command and paste your target to the text file and see if it works.
I had the same issue and it drove me crazy.
I had this error now and solved it by adding the user running typeperf to local administrators group on the servers that threw the error.
I was getting this error on a server(Windows Server 2012 R2) I had admin rights on, I had to manually build performance counters and it was sorted. Here's the link https://support.microsoft.com/en-us/help/2554336/how-to-manually-rebuild-performance-counters-for-windows-server-2008-6
The problem is that the file should contain only file names, without " quote marks.
Removing all " from counterlist resolved the issue for me.

Resources