I have an Azure WebJob console app that won't recognize the TimerTrigger that I have set up.
I have the default Program.cs generated by Visual Studio:
class Program
{
static void Main()
{
var config = new JobHostConfiguration();
if (config.IsDevelopment)
{
config.UseDevelopmentSettings();
}
var host = new JobHost();
host.RunAndBlock();
}
}
I added my new function to Functions.cs:
public static void MyFunction([TimerTrigger("0 */2 * * * *",
RunOnStartup = true)]
TimerInfo timerInfo,
TextWriter log)
{
log.WriteLine("MyFunction started!");
}
(I installed the WebJobs.Extensions NuGet package, so my code compiles fine.)
I also added this line:
config.UseTimers();
to the Main function as mentioned in this answer, but for some reason, my new function still isn't triggered.
When I start the app, I see this output:
Found the following functions:
MyNamespace.Functions.ProcessQueueMessage
Job host started
So it doesn't see my new function.
Why is this happening, and how can I fix it?
After comparing the contents of my Program.cs to what others had posted online (including the TimerTrigger docs), I found a small difference.
In the Main function, I changed:
var host = new JobHost();
to:
var host = new JobHost(config);
and it worked. I know for sure that I didn't change that before, so apparently this was a bug in the Azure WebJob template.
In the MSDN documentation for the ClaimsAuthorizationManager class, it says "You can configure your application to use a claims authorization manager ... programmatically by using the IdentityConfiguration class...". Unfortunately, neither that page nor the page for the IdentityConfiguration class have any examples of doing so. All of their examples make use of the app.config file to specify a custom ClaimsAuthorizationManager class.
I'm trying to push all of my security code into a separate library. I don't want to have to remember to copy sections of the app.config file from that library into each project that uses it.
I found a similar question regarding a custom ClaimsAuthorizationManager and DI. Sadly, that user is using something called Thinktecture.IdentityModel and their answer lies in that component and so is not available to me. However, a note on the ClaimsPrincipalPermissionAttribute class page mentions hooking into the FederationConfigurationCreated event and that appears to be how the Thinktecture.IdentityModel does it. So I tried...
class Program {
static void Main (string[] args) {
SecurityHelper s = new SecurityHelper ();
FederatedAuthentication.FederationConfigurationCreated += s.FederatedAuthentication_FederationConfigurationCreated;
SetCurrentPrincipal ();
ShowMeTheCode ();
Console.ReadLine ();
}
private static void SetCurrentPrincipal () {
WindowsPrincipal incomingPrincipal = new WindowsPrincipal (WindowsIdentity.GetCurrent ());
Thread.CurrentPrincipal = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager.Authenticate ("none", incomingPrincipal);
}
[ClaimsPrincipalPermission (SecurityAction.Demand, Operation = "List networks", Resource = "Network")]
private static void ShowMeTheCode () {
Console.WriteLine ("Console.WriteLine");
}
}
public class SecurityHelper {
public void FederatedAuthentication_FederationConfigurationCreated (object sender, System.IdentityModel.Services.Configuration.FederationConfigurationCreatedEventArgs e) {
e.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager = new CustomClaimsTransformer ();
e.FederationConfiguration.IdentityConfiguration.ClaimsAuthorizationManager = new CustomAuthorizationManager ();
}
}
This just throws an "InvalidOperationException" with a message of "Could not load the identity configuration because no configuration section was found." I'm guessing it's because the event occurs when the FederationConfiguration property is accessed for the first time by one of the HTTP modules in the web application and I'm testing in a console application.
I have a c# app using System.ServiceModel.dll. I can run the app locally, but when I try to use Power Shell to run it remotely, it hang:
Here is the simple code to recreate the problem:
using System;
using System.ServiceModel;
using System.ServiceModel.Discovery;
namespace PowerShellSecurity
{
class Program
{
static void Main(string[] args)
{
var serviceUri = "net.pipe://localhost/Foo/Bar";
var discoveryUri = new Uri("soap.udp://239.255.255.250:3702/");
var service = new MyService();
var serviceHost = new ServiceHost(service, new Uri(serviceUri));
serviceHost.Description.Behaviors.Add(new ServiceDiscoveryBehavior());
serviceHost.AddServiceEndpoint(new UdpDiscoveryEndpoint(discoveryUri));
serviceHost.AddServiceEndpoint(typeof(IMyService), new NetNamedPipeBinding(), serviceUri);
serviceHost.Open();
Console.WriteLine("It worked!");
}
}
[ServiceContract]
public interface IMyService
{
[OperationContract]
void DoStuff();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class MyService : IMyService
{
public void DoStuff()
{
throw new NotImplementedException();
}
}
}
I can run it at the localhost and it works. But if I run the following powershell command from another host:
icm -ComputerName myHost -ScriptBlock {iex "& 'c:\Users\me\Documents\Visual Studio 2013\Projects\PowerShellSecurity\PowerShellSecurity\bin\Debug\PowerShellSecurity.exe'"}
I can see the process hanging at myHost using procexp.
Then I used visual studio to attach to this process, I can see it is stuck at:
serviceHost.Open();
How can I solve this problem, if I have to use power shell to run the application remotely?
Thank you very much!
If I'm not mistaken, named pipes are local to a single computer. As far as I know, you can't connect "remotely" using named pipes.
In this case, I'd recommend using a different binding (protocol.) For example, you could use http/https, nettcp, or WSHttp.
I am unable to find a single post where i can automate mobile testing with appium in C#.
I have written my Website automation code in the specflow. Can I also Reuse it ?
Appium provides the dotnet-appium-driver which is your API to interface with Appium. You can use that to write your app automation.
You did not provide any example here nor code, so I cannot really act on something to show you. I will just write down some C# code to let you understand how a simple test in C# can be written:
namespace AppiumTests
{
using System;
// .NET unit test namespaces needed here as well, just not mentioning them
using OpenQA.Selenium; /* Appium is based on Selenium, we need to include it */
using OpenQA.Selenium.Appium; /* This is Appium */
[TestClass]
public class TestSuite
{
private AppiumDriver driver;
private static Uri testServerAddress = new Uri("http:127.0.01:4723/wd/hub"); // If Appium is running locally
private static TimeSpan INIT_TIMEOUT_SEC = TimeSpan.FromSeconds(180); /* Change this to a more reasonable value */
private static TimeSpan IMPLICIT_TIMEOUT_SEC = TimeSpan.FromSeconds(10); /* Change this to a more reasonable value */
[TestInitialize]
public void BeforeAll()
{
DesiredCapabilities testCapabilities = new DesiredCapabilities();
testCapabilities.App = "<your-app-file>";
testCapabilities.AutoWebView = true;
testCapabilities.AutomationName = "";
testCapabilities.BrowserName = String.Empty; // Leave empty otherwise you test on browsers
testCapabilities.DeviceName = "Needed if testing on IOS on a specific device. This will be the UDID";
testCapabilities.FwkVersion = "1.0"; // Not really needed
testCapabilities.Platform = TestCapabilities.DevicePlatform.Android; // Or IOS
testCapabilities.PlatformVersion = String.Empty; // Not really needed
driver = new AppiumDriver(testServerAddress, capabilities, INIT_TIMEOUT_SEC);
driver.Manage().Timeouts().ImplicitlyWait(IMPLICIT_TIMEOUT_SEC);
}
[TestCleanup]
public void AfterAll()
{
driver.Quit(); // Always quit, if you don't, next test session will fail
}
///
/// Just a simple test to heck out Appium environment.
///
[TestMethod]
public void CheckTestEnvironment()
{
var context = driver.GetContext();
Assert.IsNotNull(context);
}
}
}
You can find more in this article I wrote.
Finally reached to the solution run a test in C#. Many Thanks to Andry.
This solution runs the website in the chrome browser of your phone connected to the computer :
Steps and short program to setup and run a C# program on an android device using Appium:
namespace poc
{
using NUnit.Framework;
using System;
using OpenQA.Selenium;
using OpenQA.Selenium.Appium;
using OpenQA.Selenium.Appium.Interfaces;
using OpenQA.Selenium.Appium.MultiTouch;
using OpenQA.Selenium.Interactions;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium.Appium.Android;
[TestFixture()]
public class TestAppium
{
public IWebDriver driver;
[TestFixtureSetUp]
public void SetUp()
{
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.SetCapability("device", "Android");
capabilities.SetCapability("browserName", "chrome");
capabilities.SetCapability("deviceName", "Motorola Moto g");
capabilities.SetCapability("platformName", "Android");
capabilities.SetCapability("platformVersion", "5.0.2");
driver = new RemoteWebDriver(new Uri("http://127.0.0.1:4723/wd/hub"), capabilities, TimeSpan.FromSeconds(180));
}
[Test()]
public void OpenHofHomePage()
{
driver.Navigate().GoToUrl("http://YourWebsiteToTest.com");
Assert.IsTrue(driver.Title.Equals("Your Website")," Sorry , the website didnt open!!");
}
[TestFixtureTearDown]
public void End()
{
driver.Dispose();
}
}
}
1) Set up usual project in C# , install Appium , Selenium using NuGet package manager , Also install Nunit with the same process.
2) Download Android SDK
3) Envrionment variables : Add variable name "ANDROID_HOME" and in variable give path to sdk folder , In PATH (found in System variable) , append path to tools in sdk folder and append path to platform tools.
4) Connect your device (a.mobile device's drivers should be installed in the computer (my case moto g adb drivers installed) b. device should have developer mode option ON and debugger option checked and always awake option checked)
5) Now download Appium and open the Appium.exe.
6) Appium window -> In Android setting (first button) , check on "Use Browser" option and select "Browser" as an option.
7) Start the appium node server (play button at the top).
8) now run the test from the visual studio and you will see website opening in the browser of phone.
To make this more comprehensive, I have written a blog post which explains all the steps clearly with images. Its a step by step tutorial to use appium with c# and MSTest
You can read it here.
http://www.binaryclips.com/2016/03/test-automation-on-android-using-appium.html
This is how I have implemented Appium. I think it adds some depth to the discussion.
Appium is both a WebDriver that can interact with a device in your project as well as a Server that bridges your project to your physical device or emulator.
You have to run the Appium server as a listener and set up your Capabilities to connect to it. That will start the app and execute your test.
There is a lot more to it than this but here is a setup that you can try to get you on your way:
In a WebDriver Support Class use the [BeforeScenario] tag to execute this code before your test. This has a Sauce Labs implementation.
[BeforeScenario]
public void BeforeScenario()
{
var name = Locale == "sauce" ? "AppiumSauceDriver" : "AppiumDriver";
InitializeServiceLocator();
if (WebDriver == null)
{
InitializeWebDriver(name);
}
ObjectContainer.RegisterInstanceAs(WebDriver);
if (WebDriver != null)
{
Console.WriteLine("Driver Already Exists");
}
}
Then you need to populate the InitializeServiceLocator() method. There is a Device Selector Method here that doesn't do anything other than set the name. You can just hard code it to your capabilities instead.
private static void InitializeServiceLocator()
{
if (ServiceLocator == null)
{
var ip = "";
var deviceType = TestSetupHelper.DeviceSelector["iphone7"];
var capabilities = TestSetupHelper.SetAppiumCababilities(deviceType, Locale);
string server = MSTestContextSupport.GetRunParameter("appiumServer");
var port = Convert.ToInt32(MSTestContextSupport.GetRunParameter("appiumPort"));
if (Locale != "sauce")
{
ip = TestSetupHelper.GetComputerIpAddress(server, port, true);
}
var kernel = new StandardKernel();
kernel.Bind<IOSDriver<AppiumWebElement>>().ToConstructor(x => new IOSDriver<AppiumWebElement>(new Uri("http://" + ip + ":" + port + "/wd/hub"), capabilities, TimeSpan.FromMinutes(10))).Named("AppiumDriver");
kernel.Bind<IOSDriver<AppiumWebElement>>().ToConstructor(x => new IOSDriver<AppiumWebElement>(new Uri("http://ondemand.saucelabs.com:80/wd/hub"), capabilities, TimeSpan.FromMinutes(10))).Named("AppiumSauceDriver");
ServiceLocator = new NinjectServiceLocator(kernel);
Microsoft.Practices.ServiceLocation.ServiceLocator.SetLocatorProvider(() => ServiceLocator);
}
}
From here you need to set up your capabilities. The below method is how I have done it.
public static DesiredCapabilities SetAppiumCababilities(string deviceType, string locale, bool realDevice = false, string udid = "FAKEUDIDFOREXAMPLE")
{
string appiumAppFilePath = MSTestContextSupport.GetRunParameter("appiumAppFilePath");
//Universal Capabilities
capabilities.SetCapability("platformName", "iOS");
capabilities.SetCapability("deviceName", deviceType);
capabilities.SetCapability("automationName", "XCUITest");
capabilities.SetCapability("app", appiumAppFilePath);
capabilities.SetCapability("xcodeOrgId", "GET_THIS_FROM_APP_DEV");
capabilities.SetCapability("xcodeSigningId", "iPhone Developer");
capabilities.SetCapability("noReset", true);
capabilities.SetCapability("newCommandTimeout", 80);
if (locale == "sauce")//Sauce specific capabilities
{
capabilities.SetCapability("appiumVersion", "1.7.2");
capabilities.SetCapability("name", MSTestContextSupport.GetRunParameter("appiumJobName"));
capabilities.SetCapability("username", MSTestContextSupport.GetRunParameter("sauceId"));
capabilities.SetCapability("accessKey", MSTestContextSupport.GetRunParameter("sauceKey"));
capabilities.SetCapability("tunnel-identifier", MSTestContextSupport.GetRunParameter("sauceTunnel"));
capabilities.SetCapability("browserName", "");
capabilities.SetCapability("platformVersion", "11.2");
}
else//Local specific capabilities
{
capabilities.SetCapability("platformVersion", "11.3");
}
if (realDevice)//Sauce real device testing will not need this. This is for Local Real Device testing only
{
capabilities.SetCapability("udid", udid);
}
return capabilities;
}
Anything referencing GetRunParameter is getting a value from a .runsettings file.
Example:
<TestRunParameters>
<Parameter name="appiumJobName" value="OBI App Automated Test"/>
</TestRunParameters>
You have to add all of the stuff to the .runsettings file you are using to run the project that you want to source from there. You can hardcode it if you don't want to go through the runsettings file but I prefer to do it that way. You can make things variable that way based on the runsettings file you have selected.
Then you have to define TestSetupHelper.GetComputerIpAddress(server, port, true); If you have a hard coded IP Address to the computer that is running your Appium server you can just hard code that. Otherwise you need a Helper class somewhere (In this example it is TestSetupHelper). This example initiates a Socket Connection to the server and returns all of the details. That way you don't have to worry about IP addresses changing. You just pass the host name and the port you have Appium configured to run on and you can get the connection information from that connection and make your actual connection to the Appium Server instance.
public static string GetComputerIpAddress(string computerName, int port, bool remote)
{
var ip = "";
using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
{
socket.Connect(computerName, port);
//If remote it gets the connection destination IP, else it gets the connection initiator IP
IPEndPoint endPoint = remote ? socket.RemoteEndPoint as IPEndPoint : socket.LocalEndPoint as IPEndPoint;
ip = endPoint.Address.ToString();
}
return ip;
}
This isn't going to get you completely there but it will get you close to a working environment. Then you can start working on getting a test to actually run.
I hope this helps.
I have a windows service which i can't run or start, only install or directly debug the project.
This is my main:
namespace MyService
{
public static class Program
{
private static void Main()
{
var ServicesToRun = new System.ServiceProcess.ServiceBase[] { new Service() };
System.ServiceProcess.ServiceBase.Run(ServicesToRun);
}
}
}
And this is my Service:
public partial class Service : ServiceBase
{
private dynamic _serviceHost;
public Service()
{
this.InitializeComponent();
this.ServiceName = "MyService";
this.CanShutdown = true;
this.CanStop = true;
}
private static string HostName
{
get
{
string hostName = Dns.GetHostName();
IPHostEntry ipHostEntry = Dns.GetHostEntry(hostName);
return ipHostEntry.HostName;
}
}
protected override void OnStart(string[] args)
{
var worker = new Thread(this.InitializeHost) { Name = "Host", IsBackground = false };
worker.Start();
}
private void InitializeHost()
{
var baseAddress = new Uri(string.Format("net.tcp://{0}:{1}/MyService", HostName, "9020"));
var mexAddress = new Uri(string.Format("http://{0}:{1}/MyService", HostName, "8000"));
var cache = Factory.Create<string>("MyAssembly.MyClass", "MyAssembly");
var service = new ServiceWcf<string>(cache);
using (this._serviceHost = new Host<string>(service))
{
this._serviceHost.Open(baseAddress, mexAddress);
}
}
protected override void OnStop()
{
this._serviceHost.Dispose();
}
}
When I try to run without debugging or to start after installing the service i get the following error:
Run (directly or through VS):
Error while trying to run project: Unable to start program
'C:\path\to\my\projects\bin\Release\MyService.exe'.
The system cannot find the specified path.
Service start:
The service "MyService" on local cimpouter could not be started.
Error 3: The system cannot find the specified path.
I have no clue where the error could be.
EDIT:
private void InitializeComponent()
{
this.serviceProcessInstaller = new System.ServiceProcess.ServiceProcessInstaller();
this.serviceInstaller = new System.ServiceProcess.ServiceInstaller();
//
// serviceProcessInstaller
//
this.serviceProcessInstaller.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
this.serviceProcessInstaller.Password = null;
this.serviceProcessInstaller.Username = null;
//
// serviceInstaller
//
this.serviceInstaller.ServiceName = "MyService";
this.serviceInstaller.DisplayName = "My service";
this.serviceInstaller.Description = "My service is awesome.";
this.serviceInstaller.StartType = System.ServiceProcess.ServiceStartMode.Automatic;
//
// ProjectInstaller
//
this.Installers.AddRange(new System.Configuration.Install.Installer[] {
this.serviceProcessInstaller,
this.serviceInstaller});
}
I think this is just an issue with how the service has been registered - i.e. it's in the wrong place.
run an installutil /u [service] from a VS command prompt to uninstall any service entries you already have.
CD over to the folder where you want to run the service from - be careful here, you will have both a debug and a release build - which one do you want to be installed in the services list?
Use installutil /i [service] on the exe to reinstall.
Now it should work.
I think you might have registered the debug build first and have subsequently run a Clean operation on the build before building the Release version; thus deleting the original executable. Either that - or perhaps you moved the project after originally developing it?
Many of the developers I work with use a different folder for their local service installations that is always the same; they then deploy either a debug or release version to it; thus when they want to switch between the two they just copy different file versions over. I don't do this - I only ever register the debug build; but then I have more work to do when testing the release build :)