Details about ApplicationUnderTest.Launch() method's fileName and alternateFileName arguments - coded-ui-tests

I'm having a hard time trying to figure out some details about the arguments of the ApplicationUnderTest.Launch(String, String) method. From the MSDN page, they are described like this:
fileName
Type: System.String
The file name of the application to start.
alternateFileName
Type: System.String
The alternate file name that has environment variables.
My questions are:
What is the purpose of alternateFileName? Is it only used when fileName is not found or not valid? Does the Launch() method always try the fileName first?
Does fileName support environment variables in it? Does alternateFileName always require at least one environment variable in it?

Based on my own experience (and a little help from a decompiler), here's what I've discovered.
What is the purpose of alternateFileName?
alternateFileName allows you to use a path with environment variables that are expanded at run time. There is also some special handling to convert environment variables only found on a 64-bit environment to those found on a 32-bit environment, if necessary (for example, converting %programfiles(x86)% to %programfiles%).
Is it only used when fileName is not found or not valid? Does the Launch() method always try the fileName first?
If you use one of the Launch() overloads that include the alternateFileName parameter, it is always checked first. If there is a matching file at the expanded path, then that path is used and fileName is never checked. If there is no matching file at the expanded alternateFileName path, only then will it use fileName.
Note: I just discovered a bug present in Visual Studio 2013 Update 4 where alternateFileName is in fact incorrectly handled on a 32-bit system. In that case, alternateFileName was always getting prepended with the value C:\Windows\System32 so it would end up with a value like C:\Windows\System32C:\Program Files\foo\bar.exe. Since this is an invalid value, the system was only relying on fileName.
Does fileName support environment variables in it?
No, any environment variables in fileName are not expanded.
Does alternateFileName always require at least one environment variable in it?
No, environment variables are not required -- although I can't think of how it would be useful to supply a value for alternateFileName without them.

Here's what I do:
private static ApplicationUnderTest _application;
public static ApplicationUnderTest LaunchApplicationUnderTest(string applicationPath,
bool closeOnPlaybackCleanup)
{
Process[] processes = Process.GetProcessesByName("MyApp");
if (processes.Length > 0)
{
_application = ApplicationUnderTest.FromProcess(processes[0]);
}
else
{
_application = ApplicationUnderTest.Launch(applicationPath);
_application.CloseOnPlaybackCleanup = closeOnPlaybackCleanup;
}
return _application;
}

Related

Anchor `declare_id!` with Environment Variable - Environment Variables in Macros

In anchor the "top" of any program features a declare_id!() statement. The input to that statement is a Pubkey, typically in the form of a hard coded string. 12Factor Methodology typically dictates that hard coded configuration values like this should be avoided. However trying to not hard code the value has me pulling out my hair.
declare_id!(std::env::var("VARIABLE_NAME"));
Does not work because the env::var call executes at runtime while the macro executes at compile time.
declare_id!(env!("VARIABLE_NAME"));
Does not work because env! returns a &str.
declare_id!(Pubkey::from_str(env!("VARIABLE_NAME")));
Does not work because Pubkey::from_str can fail and as such returns a Result
declare_id!(Pubkey::from_str(env!("VARIABLE_NAME")).unwrap());
Does not work because declare_id! requires a constant and constants cannot be made from unwrap (Its probably more nuanced than that, but I'm new to rust) and ? fails for the same reason.
How would I go about defining an environment variable within a macro?
Given the lack of resources on the topic, I'm presuming an environment variable in this case is not a best practice. Why should one not use an environment variable in this case?
How can one accomplish the injection of program id into an anchor application if environment variables are not the way to do so?
Bonus points:
env::var() returns a Result<&str>
env::var_os() returns a Result<&OsStr>
env!() returns a &str
env_os!() does not exist in core
How do you handle an OsStr environment variable at build time? Why would you not need to be able to?
Working with env vars seems troublesome, since most of the ways of creating a Pubkey aren't const fn. To me, this seems like an issue with the anchor-lang crate, usually env vars aren't this troublesome.
That said, you could write the key to a config file somewhere, and read that in using include_bytes, and pass that to Pubkey::new_from_array, which is const:
// this works because concat! expands to a string literal
const BYTES: &[u8; 32] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/key"));
anchor_lang::declare_id!(Pubkey::new_from_array(*BYTES));
If you don't want to store the file in the repo, you can point include_bytes!() at any location, even one read from an env var. For example, you could have:
const BYTES: &[u8; 32] = include_bytes!(env!("ANCHOR_KEY_LOCATION"));
anchor_lang::declare_id!(Pubkey::new_from_array(*BYTES));
which will read the key bytes from a file at $ANCHOR_KEY_LOCATION

How can I determine if a string is a correctly formatted path regardless of whether it actually exists?

I am creating a function and I want to validate that a string passed in to my function is a correctly formatted path. Test-Path determines if the path exists, which I don't want. Is there a RegEx expression that can do this? Or some other native Cmdlet?
Thanks.
You can use Test-Path -IsValid to check for valid but non-existent paths:
Test-Path -LiteralPath 'C:\Whatever' -IsValid
The catch though, is that "valid" doesn't seem to mean the same thing as "correctly formatted".
For example, if I use D:\Whatever it's also valid on my machine, while E:\Whatever is not; because there is no such PSDrive (but C and D exist).
Also strange, WSman:\whatever is False while HKCU:\whatever is True.
It does seem to think UNC paths are valid.
If you're going to look at trying to validate a path another way, you could start with the set of invalid characters, which you can get with [System.IO.Path]::InvalidPathChars.
But here's something weird too, one of those characters is §, and yet C:\§whatever returns True from Test-Path -IsValid.
I'm probably raising more questions than answers here.
From comments:
I'm looking to validate a fully qualified path with drive letter and possible directories. "C:\SomeDirectory\ or D:\blah\blah"
I think the most straightforward thing to do here may be to first check if the path "is rooted", and then to cast it as a [DirectoryInfo] object:
if ([System.IO.Path]::IsPathRooted($path)) {
# this will throw an exception if the path can't be used
# for example Z:\whatever is accepted, ZZ:\whatever is not
$validatedPath = ([System.IO.DirectoryInfo]$path).FullName
}
else {
throw [System.ArgumentException]"Only fully-qualified paths are accepted."
}
You could also choose to keep the [DirectoryInfo] object rather than "converting" it back to a string with .FullName, as that object has a number of useful properties and methods, even if the directory doesn't exist.
$path = 'Z:\whatever' -as [System.IO.DirectoryInfo]
$path | Format-List *
$path | Get-Member

In IDL, how can I access a variable given its name?

I would like to convert a string to a variablename, so it can be read as a already restored variable.
So, I look through a file, and look at all the files. I use RESTORE to use the file in IDL, restore names this object as something slightly different. It names it as an object which we'll call map_1 (in the code it's called filerestore_name). This is related to the file name and I can recreate this variable name - however, its saved as a string.
Now, I pass this onto the make_cool_video procedure. However, althoughthis string now is exactly the same as the varialbe name, its still a string!.
Thus, as its a string, the procedure can't work.
filenames=FILE_SEARCH('rxrt*')
filenames_withoutextension = STREGEX(filenames,'rxrt_[0-9]+[a-zA-Z_]+',/EXTRACT,/FOLD_CASE)
restore, '/home/tomi/Documents/actualwork/'+filenames_withoutextension(18)+'.idl_sav',
filerestore_name = STRJOIN(STRSPLIT(filenameswithout(18),'_[0-9]+',/EXTRACT,/REGEX),'')
PRINT, filerestorename
make_cool_video, EXECUTE(filerestore_name),filename=filerestorenames, outdir='/path/to.file/'
retall
What I tried: using the RESTORE function and the associated RESTORED_OBJECTS to store pointers in an array, and then referring to the array. But I couldn't get the restore function to form an array.
Using EXECUTE(filerestore_name) however, this doesn't convert it as I was expecting.
I would recommend using SCOPE_VARFETCH() instead (it isn't as limited as EXECUTE() and is probably more efficient). You can do something like:
make_cool_video, (SCOPE_VARFETCH(filerestore_name)), filename=filerestorenames, outdir='/path/to.file/'
I wrote this, then immediately thought of the answer.
So,
Convert everything to a string:
string1 = "makecooljes, "+ filerestore_name, outdir='file/to/path/'"
result= EXECUTE(string1)

syslog: wrong programname in log file (#001)

I use rsyslog and want to log some actions from my application. The logging works fine and the log file will be created properly.
I formatted the output because I would like to see the programname:
rsyslog.conf:
$template usermsg,"%TIMESTAMP% %HOSTNAME% %programname% \n"
$ActionFileDefaultTemplate usermsg
Output:
Oct 14 16:28:25 box #001
I always get #001 as programname, although it should be "calculator". Does anybody have any idea how to fix that?
I create an instance of the logger in my application:
//ident = "calculator"
//facility= LOG_USER /* (1<<3) random user-level messages */
openlog(ident.c_str(), 0, facility);
At a wild guess, ident is a C++ string object of limited scope - i.e. it is most likely a local variable and the c_str() is, at best, a temporarily valid pointer.
This pointer has to remain valid for the entirety of the run of your application; openlog makes this clear in the manual:
The argument ident in the call of openlog() is probably stored as-is. Thus, if the string it points to is changed, syslog() may start prepending the changed string, and if the string it points to ceases to exist, the results are undefined. Most portable is to use a string constant.
The gnu.org manpage mentions:
Please note that the string pointer ident will be retained internally by the Syslog routines. You must not free the memory that ident points to. It is also dangerous to pass a reference to an automatic variable since leaving the scope would mean ending the lifetime of the variable. If you want to change the ident string, you must call openlog again; overwriting the string pointed to by ident is not thread-safe.
So the most likely thing is that the string variable is going out of scope, and you end up with a pointer to some random string, which in your case happens to be #001.
Solutions are many, but they all involve making sure that the data being pointed to by the c_str() don't change during the run of your application.

Use of CreateProcess on WinCE6

I'm trying to launch a process from my program, namely cmd.exe.
Doc says I have to use CreateProcess, and below is how I use it :
CreateProcess((LPCWSTR) "\Windows\cmd.exe", (LPCWSTR) "", 0,0,0,0,0,0,0,0);
dw = GetLastError();
printf("%u \n", dw);
The path is the one displayed by the target (on the target, I found a shortcut to cmd.exe which states it resides in \windows.
The error is always the same (2), regardless of how I write the path. Apparently, the error code for (2) is Invalid_Path.
Thanks for having read,
GQ
You are passing an incorrect string to create process. Just casting a byte-oriented string to LPCWSTR doesn't fix the problem that it is incorrect data - you really have to use a Unicode string, which you can spell as
CreateProcess(L"\\Windows\\cmd.exe", NULL, 0,0,0,0,0,0,0,0);
Alternatively, you can use the TEXT() macro.
The path is incorrect. Use double backslash.
CreateProcess(TEXT("\\Windows\\cmd.exe"), TEXT(""), 0,0,0,0,0,0,0,0);
Additionally, the last parameter cannot be NULL. It must be a pointer to PROCESS_INFORMATION structure. For details, see the following link
MSDN link for Creating Process in Windows CE 6.0

Resources