TFS 2015 Visual Studio Build project variables - tfs-2015

I have a Visual Studio Build definition that compiles solution1.sln. It has 2 web projects: WebProject1, and WebApiProject2.
Is there any what to get those names (WebProject1, WebApiProject2) automatically into variables?

You need to add a Powershell step to retrieve project names from a .sln file and then set the project names into variables.
Get project names:
Get-Content 'xxx.sln' |
Select-String 'Project\(' |
ForEach-Object {
$projectParts = $_ -Split '[,=]' | ForEach-Object { $_.Trim('[ "{}]') };
New-Object PSObject -Property #{
Name = $projectParts[1];
}
}
Sets a variable in the variable service of taskcontext. The first task can set a variable, and following tasks are able to use the variable. Check ##vso[task.setvariable]value for more information.
Example:
##vso[task.setvariable variable=testvar;]testvalue
##vso[task.setvariable variable=testvar;issecret=true;]testvalue

Related

Generate data seeding script using PowerShell and SSMS

Here I found a solution for the manual creation of the data seeding script. The manual solution allows me to select for which tables I want to generate the inserts
I would like to know if there is an option to run the same process via PowerShell?
So far I have managed how to create a SQL script which creates the Database schema seeder:
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | out-null
$s = new-object ('Microsoft.SqlServer.Management.Smo.Server') "(localdb)\mssqlLocalDb"
$dbs=$s.Databases
#$dbs["HdaRoot"].Script()
$dbs["HdaRoot"].Script() | Out-File C:\sql-seeding\HdaRoot.sql
#Generate script for all tables
foreach ($tables in $dbs["HdaRoot"].Tables)
{
$tables.Script() + "`r GO `r " | out-File C:\sql-seeding\HdaRoot.sql -Append
}
however is there any similar way to generate the data seeding script?
Any ideas? Cheers
You can use the SMO scripter class. This will allow you to script the table creates as well as INSERT statements for the data within the tables.
In my example I'm directly targeting TempDB and defining an array of table names I want to script out rather than scripting out every table.
Scripter has a lot of options available, so I've only done a handful in this example - the important one for this task is Options.ScriptData. Without it you'll just get the schema scripts that you're already getting.
The EnumScript method at the end does the actual work of generating the scripts, outputting, and appending the script to the file designated in the options.
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SMO') | out-null
## target file
$outfile = 'f:\scriptOutput.sql'
## target server
$s = new-object ('Microsoft.SqlServer.Management.Smo.Server') "localhost"
## target database
$db = $s.databases['tempdb']
## array of tables that we want to check
$tables = #('Client','mytable','tablesHolding')
## new Scripter object
$tableScripter = new-object ('Microsoft.SqlServer.Management.Smo.Scripter')($s)
##define options for the scripter
$tableScripter.Options.AppendToFile = $True
$tableScripter.Options.AllowSystemObjects = $False
$tableScripter.Options.ClusteredIndexes = $True
$tableScripter.Options.Indexes = $True
$tableScripter.Options.ScriptData = $True
$tableScripter.Options.ToFileOnly = $True
$tableScripter.Options.filename = $outfile
## build out the script for each table we defined earlier
foreach ($table in $tables)
{
$tableScripter.enumscript(#($db.tables[$table])) #enumscript expects an array. this is ugly, but it gives it what it wants.
}

VB.net and powershell variables

I have a Visual Studio form running with VB.net and I'm collecting info needed to setup an AD user. In the end, this info will need to simply be passed to Powershell with no return info needed. Before that though, I need it to check if a printer code has already been assigned to someone before allowing it to be submitted to another user. I have a simple powershell script written up for it.
(We use the Pager field to store the printer code.)
Import-Module ActiveDirectory
$Page = $args[0]
Get-ADUser -Filter { Pager -like $Page } | FT Name
I setup the code I found HERE, and attempted to modify it to my script but it keeps crashing on
Dim results As Collection(Of PSObject) = MyPipeline.Invoke()
It gives me: An unhandled exception of type 'System.Management.Automation.ParseException' occurred in System.Management.Automation.dll
If I run his little 6+5 basic example script, it works, but when I try to retrieve info and return a name, it doesn't like it. How can I get it to return the name of the person if it find it? And since it won't run, I'm not even sure if passing the printer code as $args[0] is going to work yet.
Your results is expecting a collection of PowerShell objects. When you pipe the Get-ADUser command to Format-Table, it effectively strips the object down to a stream of strings. Try without the | FT Name.
Import-Module ActiveDirectory #if you're using powershell 3 or later, this may be redundant
# $Page = $args[0] # don't need to do this
$results = Get-ADUser -Filter { Pager -like $args[0] }
Write-Verbose $results
#Write-Verbose $results.Name #try this if the above one works
Update:
Write-Verbose may be causing an issue.
Try this:
Get-ADUser -Filter { Pager -like $args[0] }
Just that one line as the total PS code. (Assuming you have PowerShell 3.0 or later, you don't need Import-Module) That line will return objects of type TypeName: Microsoft.ActiveDirectory.Management.ADUser (from `Get-ADUser username | Get-Member).
You may also be able to use the .Net object type directly, without PowerShell. I'm not knowledgeable about .NET beyond what I picked up working with PowerShell.
Accessing AD using .NET, info from MSDN.

Passing a variable in sqlpackage containing filepath

so i am trying to exectue a ps script directly after tfs build. while the script runs post-build there is an error that says sourcefile must have a valid .dacpac extension.
Below is the code
#Powershell script to capture the latest version of the dacpac generated for the source file
$srcdir= get-childitem '\\a\b\c\d\e\f' | Where {$_.LastWriteTime} | select -last 1
$srcpathitem= Join-Path \\a\b\c\d\e\f$srcdir
$filesource= get-childitem -path $srcpathitem -filter abc.dacpac
$finalsource= Join-Path $srcpathitem $filesource
#Latest version of the target file dacpac created
$tgtdir= get-childitem '\\1\2\3\4\5\6' | Where {$_.LastWriteTime} | select -last 1
$tgtpathitem= Join-Path \\1\2\3\4\5\6 $tgtdir
$filetarget= get-childitem -path $tgtpathitem -filter EFT.dacpac
$finaltarget= Join-Path $tgtpathitem $filesource
&"\\xyz\build\xyz\xyz\Scripts\DAC\bin\SqlPackage.exe" /a:Script `
/Sourcefile:$finalsource `
/TargetFile:$finaltarget `
/op:"\\xyz\build\xyz\xyz\Scripts\123-script.sql" `
Sorry the filelocation and folder names have been given aliases due to privacy concerns.
so the third from the last is the place where the error for dacpac is coming. so pls tell how to pass the filepath so that there isn't any error. and also FYI the path cannot be hardcoded as the folder has newer versions created after some hours automatically.
Try to use
/Sourcefile:$(finalsource)`
/TargetFile:$(finaltarget)`
instead of
/Sourcefile:$finalsource `
/TargetFile:$finaltarget `
I assume your following code can get the file successfully:
$filesource= get-childitem -path $srcpathitem -filter abc.dacpac
Then if you write out "$filesource" in powershell, you can find that the value is just "abc.dacpac'. So you can try to update "/Sourcefile:$finalsource" to "/Sourcefile:$finalsource.FullName" which will return the entire file path.

Script out all SQL objects under particular schema

Is there any way I can script out all the SQL Server objects (tables, SP, functions etc) under a schema?
In our database we have a table containing name of all the schemas and there are more than 500 schema. Some of them are for dev and some are prod. I need to script out all the objects under dev schema and create a new database.
ApexSQL Script is the tool which can be very helpful in this situation. It is the tool which creates SQL scripts for database objects, and it can script all objects into one script or all objects separately.
For this situation here is what you should do:
Select server and the database which you want to script and load them.
Go to the View tab and click the “Object filter” button, then select the “Edit filter” button:
In the Filter editor for all objects select the “Include if:” and “Click here to add filter criteria”:
Select the “Schema”, “Equals” and Enter the desired schema name, then click OK:
Click on the Home tab, check all objects and Click the “Script” button:
In the third step of the Synchronization wizard, under the Script file tab, select if you want to create one script for all objects or for each object individually from the Granularity drop down menu:
In the last step of the Script wizard click the Create button and check out the results – you will have the script which can be executed in the SQL Server Management Studio.
Thanks guys for your reply. I have solved this by generating all the scripts through SSMS and then created a schema only database. Than I dropped all the tables, views SP, functions etc those are not part of the schema I do not need.
It took me around 20 mins to do that. But after all the work is done.
This is PowerShell answer to your problem.
$Server= 'SERVER_NAME'
$Database= 'DATABASE_NAME'
$SmoScriptPath = 'SCRIPT_OUTPUT.SQL'
$Schemas = #("dlo", "deo") # include objects that fall under this schema set
$ObjectTypes = #("StoredProcedures", "Views", "Tables") #object types to be included
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("System.Data") | Out-Null
$SmoServer = new-object "Microsoft.SqlServer.Management.SMO.Server" $Server
$SmoServer.SetDefaultInitFields([Microsoft.SqlServer.Management.SMO.View], "IsSystemObject")
$SmoDb = New-Object "Microsoft.SqlServer.Management.SMO.Database"
$SmoDb = $SmoServer.Databases[$Database]
$SmoScr = New-Object "Microsoft.SqlServer.Management.Smo.Scripter"
$SmoScr.Server = $SmoServer
$SmoScr.Options = New-Object "Microsoft.SqlServer.Management.SMO.ScriptingOptions"
$SmoScr.Options.AllowSystemObjects = $false
$SmoScr.Options.IncludeDatabaseContext = $true
$SmoScr.Options.IncludeIfNotExists = $false
$SmoScr.Options.ClusteredIndexes = $true
$SmoScr.Options.Default = $true
$SmoScr.Options.DriAll = $true
$SmoScr.Options.Indexes = $true
$SmoScr.Options.NonClusteredIndexes = $true
$SmoScr.Options.IncludeHeaders = $false
$SmoScr.Options.ToFileOnly = $true
$SmoScr.Options.AppendToFile = $true
$SmoScr.Options.ScriptDrops = $false
$SmoScr.Options.Triggers = $true
$SmoScr.Options.ExtendedProperties = $true
$SmoScr.Options.FileName = $SmoScriptPath
New-Item $SmoScr.Options.FileName -type file -force | Out-Null
Foreach ($ObjectType in $ObjectTypes) {
$Objects = $SmoDb.$ObjectType | where {$_.IsSystemObject -eq $false -and $Schemas.Contains($_.Schema)}
Foreach ($Object in $Objects | where {$_ -ne $null})
{
$SmoScr.Script($Object)
}
}
If you are looking for a solution for getting these objects scripted on a schedule and checked into a GIT Repo Automatically.
Check out the following project I have shared: https://github.com/Drazzing/mssqlobjectstogit
What you get:
Changes to MS SQL Objects over time in [GIT]
Report that shows who Added / Deleted / Changed the objects over time [CSV]
Report Example:
You can use Redgate SQL Compare
or
use management studio generate script feature.

How do I get the value of a registry key and ONLY the value using powershell

Can anyone help me pull the value of a registry key and place it into a variable in PowerShell? So far I have used Get-ItemProperty and reg query and although both will pull the value, both also add extra text. I need just the string text from the registry key and ONLY the string text from the key. I'm sure I could create a function to strip off the extra text but if something changes (i.e. reg key name) it might affect this.
$key = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion'
(Get-ItemProperty -Path $key -Name ProgramFilesDir).ProgramFilesDir
I've never liked how this was provider was implemented like this : /
Basically, it makes every registry value a PSCustomObject object with PsPath, PsParentPath, PsChildname, PSDrive and PSProvider properties and then a property for its actual value. So even though you asked for the item by name, to get its value you have to use the name once more.
NONE of these answers work for situations where the value name contains spaces, dots, or other characters that are reserved in PowerShell. In that case you have to wrap the name in double quotes as per http://blog.danskingdom.com/accessing-powershell-variables-with-periods-in-their-name/ - for example:
PS> Get-ItemProperty Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7
14.0 : C:\Program Files (x86)\Microsoft Visual Studio 14.0\
12.0 : C:\Program Files (x86)\Microsoft Visual Studio 12.0\
11.0 : C:\Program Files (x86)\Microsoft Visual Studio 11.0\
15.0 : C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\V
S7
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS
PSChildName : VS7
PSProvider : Microsoft.PowerShell.Core\Registry
If you want to access any of the 14.0, 12.0, 11.0, 15.0 values, the solution from the accepted answer will not work - you will get no output:
PS> (Get-ItemProperty Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7 -Name 15.0).15.0
PS>
What does work is quoting the value name, which you should probably be doing anyway for safety:
PS> (Get-ItemProperty "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7" -Name "15.0")."15.0"
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\
PS>
Thus, the accepted answer should be modified as such:
PS> $key = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\SxS\VS7"
PS> $value = "15.0"
PS> (Get-ItemProperty -Path $key -Name $value).$value
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\
PS>
This works in PowerShell 2.0 through 5.0 (although you should probably be using Get-ItemPropertyValue in v5).
Harry Martyrossian mentions in a comment on his own answer that the
Get-ItemPropertyValue cmdlet was introduced in Powershell v5, which solves the problem:
PS> Get-ItemPropertyValue 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion' 'ProgramFilesDir'
C:\Program Files
Alternatives for PowerShell v4-:
Here's an attempt to retain the efficiency while eliminating the need for repetition of the value name, which, however, is still a little cumbersome:
& {
(Get-ItemProperty `
-LiteralPath HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion `
-Name $args
).$args
} ProgramFilesDir
By using a script block, the value name can be passed in once as a parameter, and the parameter variable ($args) can then simply be used twice inside the block.
Alternatively, a simple helper function can ease the pain:
function Get-RegValue([String] $KeyPath, [String] $ValueName) {
(Get-ItemProperty -LiteralPath $KeyPath -Name $ValueName).$ValueName
}
Note: All solutions above bypass the problem described in Ian Kemp's's answer - the need to use explicit quoting for certain value names when used as property names; e.g., .'15.0' - because the value names are passed as parameters and property access happens via a variable; e.g., .$ValueName
As for the other answers:
Andy Arismendi's helpful answer explains the annoyance with having to repeat the value name in order to get the value data efficiently.
M Jeremy Carter's helpful answer is more convenient, but can be a performance pitfall for keys with a large number of values, because an object with a large number of properties must be constructed.
I'm not sure if this has been changed, or if it has something to do with which version of PS you're using, but using Andy's example, I can remove the -Name parameter and I still get the value of the reg item:
PS C:\> $key = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion'
PS C:\> (Get-ItemProperty -Path $key).ProgramFilesDir
C:\Program Files
PS C:\> $psversiontable.psversion
Major Minor Build Revision
----- ----- ----- --------
2 0 -1 -1
Given a key \SQL with two properties:
I'd grab the "MSSQLSERVER" one with the following in-cases where I wasn't sure what the property name was going to be to use dot-notation:
$regkey_property_name = 'MSSQLSERVER'
$regkey = get-item -Path 'HKLM:\Software\Microsoft\Microsoft SQL Server\Instance Names\SQL'
$regkey.GetValue($regkey_property_name)
Well you need to be specific here. As far as I know, the key in a registry is a "folder" of properties. So did you mean get the value of a property? If so, try something like this:
(Get-ItemProperty HKLM:\Software\Microsoft\PowerShell\1\PowerShellEngine -Name PowerShellVersion).PowerShellVersion
First we get an object containing the property we need with Get-ItemProperty and then we get the value of for the property we need from that object. That will return the value of the property as a string. The example above gives you the PS version for "legacy"/compatibility-mdoe powershell (1.0 or 2.0).
Following code will enumerate all values for a certain Registry key, will sort them and will return value name : value pairs separated by colon (:):
$path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework';
Get-Item -Path $path | Select-Object -ExpandProperty Property | Sort | % {
$command = [String]::Format('(Get-ItemProperty -Path "{0}" -Name "{1}")."{1}"', $path, $_);
$value = Invoke-Expression -Command $command;
$_ + ' : ' + $value; };
Like this:
DbgJITDebugLaunchSetting : 16
DbgManagedDebugger : "C:\Windows\system32\vsjitdebugger.exe" PID %d APPDOM %d EXTEXT "%s" EVTHDL %d
InstallRoot : C:\Windows\Microsoft.NET\Framework\
Not sure at what version this capability arrived, but you can use something like this to return all the properties of multiple child registry entries in an array:
$InstalledSoftware = Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" | ForEach-Object {Get-ItemProperty "Registry::$_"}
Only adding this as Google brought me here for a relevant reason and I eventually came up with the above one-liner for dredging the registry.
If you create an object, you get a more readable output and also gain an object with properties you can access:
$path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework'
$obj = New-Object -TypeName psobject
Get-Item -Path $path | Select-Object -ExpandProperty Property | Sort | % {
$command = [String]::Format('(Get-ItemProperty -Path "{0}" -Name "{1}")."{1}"', $path, $_)
$value = Invoke-Expression -Command $command
$obj | Add-Member -MemberType NoteProperty -Name $_ -Value $value}
Write-Output $obj | fl
Sample output:
InstallRoot : C:\Windows\Microsoft.NET\Framework\
And the object:
$obj.InstallRoot = C:\Windows\Microsoft.NET\Framework\
The truth of the matter is this is way more complicated than it needs to be. Here is a much better example, and much simpler:
$path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework'
$objReg = Get-ItemProperty -Path $path | Select -Property *
$objReg is now a custom object where each registry entry is a property name. You can view the formatted list via:
write-output $objReg
InstallRoot : C:\Windows\Microsoft.NET\Framework\
DbgManagedDebugger : "C:\windows\system32\vsjitdebugger.exe"
And you have access to the object itself:
$objReg.InstallRoot
C:\Windows\Microsoft.NET\Framework\