I am creating an application to manage ad groups through MVC using Power Shell Script Interaction. I have created a function that will return the values to fill in the razor components of HTML. However, when I passing the shell scripts from the base directory location the component is not getting filled with the value.
I have tried to set the path of the script using AppDomain.CurrentDomain.BaseDirectory, there is no error being generated nor I am getting any output.
** Razor Code **
#functions {
public string PowerShellExecutor(string script) {
var shell = PowerShell.Create();
string outString = "";
shell.Commands.AddScript(script);
var results = shell.Invoke();
if (results.Count>0)
{
var builder = new StringBuilder();
foreach (var psObj in results)
{
builder.Append(psObj.BaseObject.ToString() + "\r\n");
}
outString = Server.HtmlEncode(builder.ToString());
}
return outString;
}
<div class="row">
<div class="col-md-12">
#Html.TextBox("txtDir", #PowerShellExecutor(AppDomain.CurrentDomain.BaseDirectory.ToString()+ "Shell\\Get-StewardName.ps1"), new { #class = "form-control" })
#*#Html.TextBox("txtDirectory", #PowerShellExecutor("$env:USERDNSDOMAIN") , new { #class = "form-control"})*#
</div>
</div>
** Powershell Script **
$StewardName = Get-ADUser $env:USERNAME -Properties DisplayName | Select -ExpandProperty DisplayName
$EmployeeNumber = Get-ADUser $env:UserName -Properties EmployeeNumber| Select -ExpandProperty EmployeeNumber
Write-Output "Steward: $StewardName ($EmployeeNumber)"
When I type the environment variables I get the domain I am member of. When I pass script it should be getting some value.
Ok, so replacing AddScript() with AddCommand() executes the script however, while using environment variables to fetch the data it throws command not found exception.
Related
I am trying to pass arguments to MSBuild 2.0. After research it appears that I need to do this using variables, but I cannot figure out how to incorporate this into my queue request below. I have tried parameters but that does not seem to work. Here is what I am trying to tell MSBuild #" /p:OctoPackPackageVersion=" + releaseNumber. This worked with the XAML build using IBuildRequest.ProcessParameters.
var buildClient = new BuildHttpClient(new Uri(collectionURL), new
VssCredentials(true));
var res = await buildClient.QueueBuildAsync(new Build
{
Definition = new DefinitionReference
{
Id = targetBuild.Id
},
Project = targetBuild.Project,
SourceVersion = ChangeSetNumber,
Parameters = buildArg
});
return res.Id.ToString();
vNext build system is different with legacy XAML build system, you cannot pass variable to build tasks in the build definition directly when queue the build. The code you used updated the build definition before queue the build which means that the build definition may keep changing if the variable changed.
The workaround for this would be add a variable in your build definition for example "var1" and then use this variable as the arguments for MSBuild Task:
With this, you will be able to pass the value to "var1" variable when queue the build without updating the build definition.
Build build = new Build();
build.Parameters = "{\"var1\":\"/p:OctoPackPackageVersion=version2\"}";
// OR using Newtonsoft.Json.JsonConvert
var dict = new Dictionary<string, string>{{"var1", "/p:OctoPackPackageVersion=version2"}};
build.Parameters = JsonConvert.SerializeObject(dict)
I have found this solution and it works for me excellent. I set custom parameters for convenience in build definition without updating on server:
foreach (var variable in targetBuildDef.Variables.Where(p => p.Value.AllowOverride))
{
var customVar = variables.FirstOrDefault(p => p.Key == variable.Key);
if (customVar == null)
continue;
variable.Value.Value = customVar.Value.TrimEnd('\\');
}
And then set variables values in build parameters:
using (TfsTeamProjectCollection ttpc = new TfsTeamProjectCollection(new Uri(tFSCollectionUri)))
{
using (BuildHttpClient buildServer = ttpc.GetClient<BuildHttpClient>())
{
var requestedBuild = new Build
{
Definition = targetBuildDef,
Project = targetBuildDef.Project
};
var dic = targetBuildDef.Variables.Where(z => z.Value.AllowOverride).Select(x => new KeyValuePair<string, string>(x.Key, x.Value.Value));
var paramString = $"{{{string.Join(",", dic.Select(p => $#"""{p.Key}"":""{p.Value}"""))}}}";
var jsonParams = HttpUtility.JavaScriptStringEncode(paramString).Replace(#"\""", #"""");
requestedBuild.Parameters = jsonParams;
var queuedBuild = buildServer.QueueBuildAsync(requestedBuild).Result;
First, the new build on TFS2015 which is called vNext build not MSbuild 2.0.
Which you are looking for should be Build variables. Variables give you a convenient way to get key bits of data into various parts of your build process. For the variable with Allow at queue time box checked you could be enable allow your team to modify the value when they manually queue a build.
Some tutorials may be helpful for using variables:
TFS Build 2015 (vNext) – Scripts and Variables
Passing Visual Studio Team Services build properties to MSBuild
Patrick, I was able to find a work around to my issue by updating the build definition. This is definitely not ideal but it works. As you can see below I am trying to add to the msbuild args already present. If you know a better way let me know. I really appreciate you taking the time to look at my question.
public static async Task<string> QueueNewBuild(string project, BuildDefinitionReference targetBuild, string collectionURL, string ChangeSetNumber, string ReleaseNumber, bool CreateRelease)
{
var buildClient = new BuildHttpClient(new Uri(collectionURL), new VssCredentials(true));
await Task.Delay(1000).ConfigureAwait(false);
var buildDef = await buildClient.GetDefinitionAsync(targetBuild.Project.Id, targetBuild.Id);
BuildDefinitionVariable OrigMSbuildvar = buildDef.Variables["MSBuildArgs"];
buildDef.Variables["MSBuildArgs"].Value = OrigMSbuildvar.Value + " /p:OctoPackPackageVersion=" + ReleaseNumber.ToString();
await Task.Delay(1000).ConfigureAwait(false);
buildDef = await buildClient.UpdateDefinitionAsync(buildDef);
await Task.Delay(1000).ConfigureAwait(false);
Build build = new Build
{
Definition = new DefinitionReference
{
Id = targetBuild.Id
},
Project = targetBuild.Project,
SourceVersion = ChangeSetNumber
};
await Task.Delay(1000).ConfigureAwait(false);
var res = await buildClient.QueueBuildAsync(build);
buildDef.Variables["MSBuildArgs"].Value = OrigMSbuildvar.Value;
await Task.Delay(1000).ConfigureAwait(false);
buildDef = await buildClient.UpdateDefinitionAsync(buildDef);
return res.Id.ToString();
}
I am looking for UFT and TFS integration (Run test from TFS like we did with HPQC)
I search on google but no help . If anyone know how to do this please let me know steps.
Thanks
You can use Generic Test to call QTP during the testing in TFS. Make sure QTP is installed on the test agent. See the code here for reference:
QTP TFS Generic Test Integration.
One more link for reference: Executing remote QTP scripts via Test Agents and Test Controllers.
Take a look at a solution from OpsHub.
More details:
Announcement:
http://blogs.msdn.com/b/visualstudioalm/archive/2013/05/16/enabling-seamless-integration-with-team-foundation-server-microsoft-test-professional-and-hp-alm-with-opshub-v5-3.aspx
Video:
http://opshub.com/ohrel/Resources/Videos/QTP_MTM_Video/QTP_MTM_Video.mp4
Case study:
https://customers.microsoft.com/Pages/CustomerStory.aspx?recid=17218
Take a look into this code:
import QTObjectModelLib dll from C:\Program Files (x86)\HP\Unified Functional Testing\bin location to your solution.
public void Fn_QTP()
{
qtApp.Launch();
qtApp.Visible = true;
qtApp.Options.Run.RunMode = "Fast";
qtApp.Options.Run.StepExecutionDelay = 0;
qtApp.Options.Run.ViewResults = false;
qtApp.Test.Settings.Run.OnError = "Stop";
//iterate for all test cases under selected module
// oTestSuiteDict : this dictionary conatins all the testsuites from TFS which meant to be executed.
//keys have their ID's
foreach (var item in oTestSuiteDict.Keys)
{
foreach (var TestCase in oTestSuiteDict[item].Keys)
{
Console.WriteLine("Executing TestCase : {0}", TestCase);
//update the XML file and upload in QTP
//this XML file is used to provide the data to QTP as a environment variables.
Fn_UpdateXMLFile(item, TestCase);
//Open the test Case
string scriptPath = #"path of script that will be opened in QTP (Action)";
qtApp.Open(scriptPath, true, false);
// Get a reference to the test object
qtTest = qtApp.Test; // Get reference to test object opened/created by application
qtTest.Settings.Run.OnError = "NextStep";
//check if the library is already associated.
if (qtTest.Settings.Resources.Libraries.Find(#"library path") == 1)
{
qtTest.Settings.Resources.Libraries.RemoveAll();
}
qtTest.Settings.Resources.Libraries.Add(#"Library Path");
//Console.WriteLine("Library is associated with Test");
// Get a reference to the Results Object for test results location
QTObjectModelLib.RunResultsOptions qtRRO = new QTObjectModelLib.RunResultsOptions();
// Run the test
//creates and start the instance of Stopwatch just to track the time period of testcase execution.
Stopwatch stopwatch = Stopwatch.StartNew();
qtTest.Run(qtRRO, true, null); // run the test
stopwatch.Stop();
string oTime = stopwatch.Elapsed.ToString();
oTestCaseTime.Add(TestCase, oTime);
string ostatus = qtTest.LastRunResults.Status;
oResults.Add(TestCase, ostatus);
qtTest.Close(); // Close the test
}
}
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(qtTest); // Cleanly release COM object
qtTest = null; // set object to null
//break;
//qtApp.Quit(); // Quit QTP
GC.Collect(); // Garbage collect
GC.WaitForPendingFinalizers(); // Wait for GC
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(qtApp); // Cleanly release COM Object
qtApp = null; // set to null
}
// Fn_UpdateXMLFile : function to update environment variables for qtp
//module name : the testsuite name(contains list of testcases); testcasename : testcases listed in modulename(test suite)
public void Fn_UpdateXMLFile(string modulename,string testcasename)
{
string oPath = #"path of xml file";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(oPath);
XmlNodeList nodes = xmlDoc.SelectNodes("Environment/Variable/Value");
nodes[0].InnerText = modulename;
nodes[1].InnerText = testcasename;
xmlDoc.Save(oPath);
}
//format of XML file :
<Environment>
<Variable>
<Name>ModuleName</Name>
<Value>ToolsMenu</Value>
</Variable>
<Variable>
<Name>""</Name>
<Value>""</Value>
</Variable>
</Environment>
The script is not iterating through all the values of the 'modules' array.
class Module {
public String name = '';
public Boolean isCustom = false;
public Module(String name, Boolean custom){
this.name = name;
this.isCustom = custom;
}
}
//creates array from the ext_module env var
modules = [];
EXT_MODULE.split(',').each {
modules.add(new Module(it, false));
}
println modules;
modules.each {
println "MODULE NAME ::::: ${it.name}"
if(it.isCustom)
{
println "install custom";
} else {
println "install non custom";
}
};
This is the result of the run. The array shows 4 elements, but the code inside the .each black only executes once.
Running: Print Message
[Module#71f09325, Module#e1ddb41, Module#7069a674, Module#1f68f952]
Running: Print Message
MODULE NAME ::::: puppetlabs-ntp
Running: Print Message
install non custom
Running: End of Workflow
Finished: SUCCESS
The messages "Running: Print Message" and "Running: End of Workflow" indicate that you are using the new workflow plugin: https://wiki.jenkins-ci.org/display/JENKINS/Workflow+Plugin. This plugin currently has a bug causing at least some Groovy iterations involving a closure to be aborted after one iteration: https://issues.jenkins-ci.org/browse/JENKINS-26481
The workaround is to simply use an old school for loop (code below).
Also, NonCPS is another workaround.
There is an open issue for this matter. See here: https://issues.jenkins-ci.org/browse/JENKINS-26481
Update, Oct 24th, 2016
/**
* Dumps environment varibles to the log, using an old school for loop.
*/
import com.cloudbees.groovy.cps.NonCPS
def version = '1.0'
#NonCPS
def dumpEnvVars() {
def str = "Dumping build environment variables...\n"
for (Map.Entry<String, String> entry : currentBuild.build().environment) {
str += " ${entry.key} = ${entry.value}\n"
}
echo str
}
return this;
As of yesterday, the new Pipeline plugin was delivered in version 2.0 and correct this problem.
.each closures now work, but .collect still only iterate once.
I am trying to set up an autocomplete input box on a form and although everything seems to work I an getting no data passed to the input box. Firebug reports a success but nothing there. I was wondering if some one could look at my code to see if there are any glaring errors that may be causing it.
Script is:
(function($){
$("#town").autocomplete({
source :"drivers/driver_gettown",
minLength : 3,
dataType:'JSON',
type:'POST'
});
})(jQuery);
Input Box is:
<div class="div">
<input name="town" id="town" type="text" class="txtSelect input required" value="<?php echo set_value('town'); ?>" />
<?php echo form_error('town'); ?>
</div>
Model is:
class Driver_model extends CI_Model
{
public function __construct() {
// Load the Database
parent::__construct();
$this->load->database();
}
function driver_get_towns($q)
{
// Get a list of Towns
// Search for row "place_name" from Table called "tbk_towns"
$this->db->select('place_name');
$this->db->like('place_name', $q);
$query = $this->db->get('tbk_towns');
if($query->num_rows > 0)
{
foreach ($query->result_array() as $row)
{
//build an array for the towns
$row_set[] = htmlentities(ucfirst($row['place_name']));
}
//format the array into json data
// header('Content-Type: application/x-json; charset=utf-8');
// echo json_encode($row_set);
$this->output
->set_content_type('application/json')
->set_output(json_encode($row_set));
}
}
}
and Finally the controller:
class Drivers extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->load->model('driver_model');
$this->load->helper('url', 'form', 'html', 'json');
}
function index()
{
// Just loads the main Page of the Drivers Area
$data['metatitle'] = "Auto Ninja | Drivers Members Area | Locally Rated Garages & Mechanics";
$data['metadescription'] = "Garages & Mechanics";
$data['metakeywords'] = "Car Repair, Car Service, Car MOT";
$this->load->view('drivers/header_drivers.inc.php', $data);
$this->load->view('drivers/index');
$this->load->view('drivers/footer_index.inc.php');
}
public function driver_gettown()
{
if (isset($_GET['term'])){
exit;
}
$this->load->model('driver_model');
$q = ucfirst($_GET['term']);
$this->driver_model->driver_get_towns($q);
}
}
and comments/help would be gratefully appreciated.
function driver_addjob()
{
// Loads the Add New Job Form for the Website
$this->load->helper('form');
$this->load->library(array('form_validation', 'session'));
$this->load->model('driver_model');
$this ->form_validation->set_error_delimiters('<span class="error">', '</span>');
// Validate the form fields
$this->form_validation->set_rules('town', 'Nearest Town or City', 'trim|required|xss_clean');
// Populates dropdown "town" from the database ???
if ($this->form_validation->run() == FALSE)
{
$data['metatitle'] = "Auto Ninja | Drivers - Add New Job | Locally Rated Garages & Mechanics";
$data['metadescription'] = "Garages & Mechanics";
$data['metakeywords'] = "Car Repair, Car Service, Car MOT";
$this->load->view('drivers/header_drivers.inc.php', $data);
$this->load->view('drivers/driver_addjob.php');
$this->load->view('drivers/footer_index.inc.php');
}
else
{
$townid = $this->input->post('town');
$work_jobtitle = $this->input->post('jobtitle');
$this->driver_model->driver_add_job ($townid);
$this->session->set_flashdata('message', 'your work request has been added to the system');
$data['metatitle'] = "Auto Ninja | Drivers - Add New Jobs Success | Locally Rated Garages & Mechanics";
$data['metadescription'] = "Garages & Mechanics";
$data['metakeywords'] = "Car Repair, Car Service, Car MOT";
$this->load->view('drivers/header_drivers.inc.php', $data);
$this->load->view('drivers/driver_addjob_success');
$this->load->view('drivers/footer_index.inc.php');
}
}
Ok I finally figured this one out. For some reason the response URL is coming out at
http://php.codeigniter.server/drivers/drivers/driver_gettown?term=ed
so the controller is being added twice. I updated the Java to
(function($){
$("#town").autocomplete({
source :"driver_gettown",
minLength : 3,
dataType:'JSON',
type:'POST'
});
})(jQuery);
ie not including the controller and it works!!! So a tad confused as to how it knows which controller to find the method in but who cares it works. It would be nice to know though as it will probably still annoy me... Possibly the JSON call bring it over in the URL maby?
can't run the automated project in testcomplete when calls from jenkins.
In our continuous integration part ,the project is automated using testcomplete and it is calling through jenkins with the help of bat file.The scripts inside the bat file is
"C:\Program Files\Automated QA\TestComplete 7\Bin\TestComplete.exe " "D:\Test Complete7 Projects\ProjectInput_AllSamples\ProjecInputs.pjs" /r /p:Samples /rt:Main "iexplore" /e
It will open testcomplete and iexplorer ,but it is not filling the data(automation).
It is working perfectly when we directly call the bat file with out jenkins.Is there any solution
From your description it sounds like something in Windows stopping you from allowing your test application to work normally. It might be the fact that the second user could be a problem but I can't confirm that as I was not able find any definite explanations of how it works in Windows XP. I am pretty sure that this won't work on a Windows Vista, 7, 8 or server machine though because of the changes in architecture.
It sounds like the best solution is to make sure that your automated UI tests are started by an interactive user. When I was trying to add automated testing to our builds we used TestComplete 7 on a Windows XP SP2 virtual machine. In order to start our tests as an interactive user we:
Made an user log on when windows started, this way there was always an interactive user which means there was an actual desktop session which has access to the keyboard / mouse. I seem to remember (but can't find any links at the moment) that without an interactive user there is no active desktop that can access the keyboard / mouse.
We wrote a little app that would start when the interactive user logged on. This app would look at a specific file and when that file changed / was created it would read the file and start the application. The code for this app looked somewhat like this:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ApplicationStarter
{
class Program
{
// The string used to indicate that the application should quit.
private const string ExitString = "exit";
// The path which is being watched for changes.
private static string s_LoadFilePath;
static void Main(string[] args)
{
try
{
{
Debug.Assert(
args != null,
"The arguments array should not be null.");
Debug.Assert(
args.Length == 1,
"There should only be one argument.");
}
s_LoadFilePath = args[0];
{
Console.WriteLine(
string.Format(
CultureInfo.InvariantCulture,
"Watching: {0}",
s_LoadFilePath));
}
if (File.Exists(s_LoadFilePath))
{
RunApplication(s_LoadFilePath);
}
using (var watcher = new FileSystemWatcher())
{
watcher.IncludeSubdirectories = false;
watcher.NotifyFilter =
NotifyFilters.LastAccess
| NotifyFilters.LastWrite
| NotifyFilters.FileName
| NotifyFilters.DirectoryName;
watcher.Path = Path.GetDirectoryName(s_LoadFilePath);
watcher.Filter = Path.GetFileName(s_LoadFilePath);
try
{
watcher.Created += OnConfigFileCreate;
watcher.EnableRaisingEvents = true;
// Now just sit here and wait until hell freezes over
// or until the user tells us that it has
string line = string.Empty;
while (!string.Equals(line, ExitString, StringComparison.OrdinalIgnoreCase))
{
line = Console.ReadLine();
}
}
finally
{
watcher.Created -= OnConfigFileCreate;
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
private static void RunApplication(string configFilePath)
{
var appPath = string.Empty;
var arguments = string.Empty;
using (var reader = new StreamReader(configFilePath, Encoding.UTF8))
{
appPath = reader.ReadLine();
arguments = reader.ReadLine();
}
// Run the application
StartProcess(appPath, arguments);
}
private static void StartProcess(string path, string arguments)
{
var startInfo = new ProcessStartInfo();
{
startInfo.FileName = path;
startInfo.Arguments = arguments;
startInfo.ErrorDialog = false;
startInfo.UseShellExecute = true;
startInfo.RedirectStandardOutput = false;
startInfo.RedirectStandardError = false;
}
Console.WriteLine(
string.Format(
CultureInfo.InvariantCulture,
"{0} Starting process {1}",
DateTime.Now,
path));
using (var exec = new Process())
{
exec.StartInfo = startInfo;
exec.Start();
}
}
private static void OnConfigFileCreate(
object sender,
FileSystemEventArgs e)
{
Console.WriteLine(
string.Format(
CultureInfo.InvariantCulture,
"{0} File change event ({1}) for: {2}",
DateTime.Now,
e.ChangeType,
e.FullPath));
// See that the file is there. If so then start the app
if (File.Exists(e.FullPath) &&
string.Equals(s_LoadFilePath, e.FullPath, StringComparison.OrdinalIgnoreCase))
{
// Wait for a bit so that the file is no
// longer locked by other processes
Thread.Sleep(500);
// Now run the application
RunApplication(e.FullPath);
}
}
}
}
This app expects the file to have 2 lines, the first with the app you want to start and the second with the arguments, so in your case something like this:
C:\Program Files\Automated QA\TestComplete 7\Bin\TestComplete.exe
"D:\Test Complete7 Projects\ProjectInput_AllSamples\ProjecInputs.pjs" /r /p:Samples /rt:Main "iexplore" /e
You should be able to generate this file from Jenkins in a build step.
Finally you may need to watch the TestComplete process for exit so that you can grab the results at the end but I'll leave that as an exercise to reader.
If you are running Jenkins (either master or slave) as a windows service, ensure it is running as a user and not as Local System.
We also do the same as Gentlesea's recommends, we run TestExecute on our Jenkins Slaves and keepo the TestComplete licenses for the people designing the TestComplete scripts.