Console Application to mount azure cloud drive - c#

I want to mount vhd from my private container. After google I get that it is only possible through .net. I am more of a JAVA person. I need a batch script or code in c# (So that I can get an exe file) which can automatically run at startup and mount vhd. So I decided to create a console app in order to get exe file.(I have very less knowledge c#/Visual studio) I am using following C# console application to do this.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Threading;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.Diagnostics;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.StorageClient;
using Microsoft.WindowsAzure.Internal;
namespace WorkerRole1
{
public class WorkerRole : RoleEntryPoint
{
public override void Run()
{
// This is a sample worker implementation. Replace with your logic.
Trace.WriteLine("WorkerRole1 entry point called", "Starting");
MountDrive();
//while (true)
//{
// Thread.Sleep(10000);
// Trace.WriteLine("Working", "Information");
//}
}
public override bool OnStart()
{
// Set the maximum number of concurrent connections
ServicePointManager.DefaultConnectionLimit = 12;
// For information on handling configuration changes
// see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
return base.OnStart();
}
public void MountDrive()
{
string connectionStringSettingName = "DefaultEndpointsProtocol=http;AccountName=abc;AccountKey=xyz";
string azureContainerName = "vhds";
string vhdName = "myvhd.vhd";
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionStringSettingName);
//CloudStorageAccount storageAccount = CloudStorageAccount.DevelopmentStorageAccount;
LocalResource localCache = RoleEnvironment.GetLocalResource("MyAzureDriveCache");
CloudDrive.InitializeCache(localCache.RootPath, localCache.MaximumSizeInMegabytes);
Trace.WriteLine("RootPath =====" + localCache.RootPath);
Trace.WriteLine("MaximumSizeInMegabytes =====" + localCache.MaximumSizeInMegabytes);
// Just checking: make sure the container exists
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
blobClient.GetContainerReference(azureContainerName).CreateIfNotExist();
// Create cloud drive
CloudDrive myCloudDrive = storageAccount.CreateCloudDrive(
blobClient
.GetContainerReference(azureContainerName)
.GetPageBlobReference(vhdName)
.Uri.ToString()
);
Trace.WriteLine("Uri =====" + blobClient
.GetContainerReference(azureContainerName)
.GetPageBlobReference(vhdName)
.Uri.ToString());
try
{
myCloudDrive.Create(1024);
}
catch (CloudDriveException ex)
{
// handle exception here
// exception is also thrown if all is well but the drive already exists
}
string driveLetter = myCloudDrive.Mount(50, DriveMountOptions.Force);//Here It throws a Exception
Trace.WriteLine("Drive =====" + driveLetter);
for (int i = 0; i < 10; i++)
{
System.IO.File.WriteAllText(driveLetter + "\\" + i.ToString() + ".txt", "Test");
}
}
}
}
But I keep getting exception ERROR_DEVFABRIC_LOCAL_MOUNT_ONLY at
string driveLetter = myCloudDrive.Mount(50, DriveMountOptions.Force);
Please tell me where am I going wrong?

When RoleEnvironment.IsAvailable is set to false, this means you are not running in a Windows Azure Web/Worker/VM Role. The Windows Azure Drive only works when mounted in these roles (since it depends on RoleEnvironment).
More information can be found in the whitepaper.

ERROR_DEVFABRIC_LOCAL_MOUNT_ONLY means that when you are running locally you must mount the drive form development storage.
change the following line:
string connectionStringSettingName = "UseDevelopmentStorage=true";
or even better use RoleEnvironment.GetConfigurationSettingValue, like:
string connectionStringSettingName = RoleEnvironment.GetConfigurationSettingValue("DriveConnectionString");
and set the Setting in the service configuration (files)

Related

c# Upload File to SharePoint Document Library

My requirement is the following:
I have various bits of network hardware, from which we regularly export configurations (this is done using another c#/.NET app I created, this works really well - the tool logs in via SSH to the various devices and downloads the latest configuration to the local hard disk of the server from which the app runs).
We have various SharePoint online sites (provided via our M365 subscription).
I want to have these configs uploaded to a particular folder, in a particular document library, in a particular SharePoint Online site, basically so that there is an off-site backup of the config files.
I was following the steps in this blog: https://daoudisamir.com/from-c-to-sharepoint-file-upload-using-csom-with-subfolders-structure/.
It looked like it did what I wanted... but when I try to build the code, it tells me that I'm missing references to assemblies etc. I know that this means that I'm missing "using" directives, but I've tried all sorts of variations to reference the various NUGET packages that are instructed to be installed, but I can't get this to work and couldn't see anywhere on the blog itself to email the owner.
Anyone got any ideas... at the moment, my code is more or less a copy/paste of what's on the blog page, but I've included my code here for convenience:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
using System.Security;
using System.IO;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Client;
namespace UploadToSharePoint_Net48
{
internal class Program
{
static void Main(string[] args)
{
string SiteUrl = "https://You.sharepoint.com/sites/Upload";
string DocumentLibrary = "UploadLibrary";
string FileName = #"C:\testupload.pdf";
string CustomerFolder = "1564_dsfgsst";
string UserName = "samir.daoudi#******.co.uk";
string Password = "*****";
UploadFileToSharePoint(SiteUrl, DocumentLibrary, CustomerFolder, FileName, UserName, Password);
}
private static void UploadFileToSharePoint(string SiteUrl, string DocLibrary, string ClientSubFolder, string FileName, string Login, string Password)
{
try
{
#region ConnectToSharePoint
var securePassword = new SecureString();
foreach (char c in Password)
{ securePassword.AppendChar(c); }
var onlineCredentials = new SP.SharePointOnlineCredentials(Login, securePassword);
#endregion
#region Insert the data
using (SP.ClientContext CContext = new SP.ClientContext(SiteUrl))
{
CContext.Credentials = onlineCredentials;
SP.Web web = CContext.Web;
SP.FileCreationInformation newFile = new SP.FileCreationInformation();
byte[] FileContent = System.IO.File.ReadAllBytes(FileName);
newFile.ContentStream = new MemoryStream(FileContent);
newFile.Url = Path.GetFileName(FileName);
SP.List DocumentLibrary = web.Lists.GetByTitle(DocLibrary);
//SP.Folder folder = DocumentLibrary.RootFolder.Folders.GetByUrl(ClientSubFolder);
SP.Folder Clientfolder = DocumentLibrary.RootFolder.Folders.Add(ClientSubFolder);
Clientfolder.Update();
SP.File uploadFile = Clientfolder.Files.Add(newFile);
CContext.Load(DocumentLibrary);
CContext.Load(uploadFile);
CContext.ExecuteQuery();
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("The File has been uploaded" + Environment.NewLine + "FileUrl -->" + SiteUrl + "/" + DocLibrary + "/" + ClientSubFolder + "/" + Path.GetFileName(FileName));
}
#endregion
}
catch (Exception exp)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(exp.Message + Environment.NewLine + exp.StackTrace);
}
finally
{
Console.ReadLine();
}
}
}
}
The errors are with all the references to SP.xxxxx
I can see that there is no definition for anything called "SP", but I'm assuming at this stage that this is in one of the external libraries or whatever is in the NUGETS that are required.
Any help gratefully received.
Thanks
Colin

Google Vision API not working Grpc.Core.RpcException

I'm trying to get Google Vision API to work with my project but having trouble. I keep getting the following error:
Grpc.Core.RpcException: 'Status(StatusCode=PermissionDenied, Detail="This API method requires billing to be enabled
I've created a service account, billing is enabled and I have the .json file. I've got the Environment variable for my account for GOOGLE_APPLICATION_CREDENTIALS pointing to the .json file.
I've yet to find a solution to my problem using Google documentation or checking StackOverFlow.
using Google.Cloud.Vision.V1;
using System;
using System.Collections.Generic;
namespace Vision
{
internal static class GoogleVision
{
public static EntityAnnotation[] GetAnnotations(EventManager em, string filePath, string EventNr)
{
{
ImageAnnotatorClient Client = ImageAnnotatorClient.Create();
Image Image = Google.Cloud.Vision.V1.Image.FromFile(filePath);
IReadOnlyList<EntityAnnotation> Response = Client.DetectLabels(Image);
EntityAnnotation[] annotations = new EntityAnnotation[Response.Count];
for (int i = 0; i < annotations.Length; i++)
{
annotations[i] = Response[i];
}
return annotations;
}
}
}
}
Not sure why but by setting the environment variable in the code rather than manually with windows, it fixed the problem.
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", "thejsonfile");

Vs.Net C# Azure flle storage fails to add File for existing File Share

VS.NET C# fails to create file on Azure File Storage for Existing File share
I'm using Microsoft.WindowsAzure.Storage lib to access Azure File Storage API. My method creates File Share and uploads file. It works when File Share is created, but skips file upload when File Share exists.
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
public void SaveText( string fileName )
{
string accountName = "mylogs";
string key = #"dvjdjhsvdjfhvsjhdvfjhsvdfjhC2g==";
var storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, key), true);
var share = storageAccount.CreateCloudFileClient().GetShareReference("test");
share.CreateIfNotExistsAsync().Wait();
var root = share.GetRootDirectoryReference();
root.GetFileReference(fileName).UploadTextAsync("mytext").Wait();
}
First SaveText(file1) call works fine, Share & "file1" got created.
Second SaveText(file2) call, no errors, no "file2" created.
Same user, same app.
I'm using the nuget package WindowsAzure.Storage, version 9.3.3, and with a console project(not .net core), it works fine.
Sample code as blow(just use yours):
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using System;
namespace AzureFileTest
{
class Program
{
static void Main(string[] args)
{
Program p = new Program();
p.SaveText("file1"); //in the first call, file1 created and text uploads.
p.SaveText("file2"); //in the second call, file2 created and text uploads.
Console.WriteLine("done now");
Console.ReadLine();
}
public void SaveText(string fileName)
{
string accountName = "xxxxx";
string key = "xxxxxx";
var storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, key), true);
var share = storageAccount.CreateCloudFileClient().GetShareReference("test");
share.CreateIfNotExistsAsync().Wait();
var root = share.GetRootDirectoryReference();
root.GetFileReference(fileName).UploadTextAsync("mytext").Wait();
}
}
}
Please let me know if any more issues, or any difference between the codes.

Creating running and installing windows services - How to appropriately send a control request to the SCM

I've been struggling with this windows service now for almost two weeks, I have scoured the internet for a resolution and in the process I have learned a lot except that I have not been able to resolve my issue.
I can't seem to find the right way to compose and run a service. There are some articles and opinions on this question even on SO but most of the questions on SO don't even have an acceptable answer, I'm hoping my question will be better accepted by the community so we can settle this windows service issue once and for all.
First of all I have set my configuration mode to debug on x86 (Internal reason for this). I have an installer class as follows:
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Linq;
using System.ServiceProcess;
using System.Threading.Tasks;
namespace Practique
{
[RunInstaller(true)]
public partial class Installer1 : System.Configuration.Install.Installer
{
public Installer1()
{
InitializeComponent();
ServiceProcessInstaller serviceProcessInstaller = new ServiceProcessInstaller();
ServiceInstaller serviceInstaller = new ServiceInstaller();
//# Service Account Information
serviceProcessInstaller.Account = ServiceAccount.LocalSystem;
serviceProcessInstaller.Username = null;
serviceProcessInstaller.Password = null;
//# Service Information
serviceInstaller.DisplayName = "Practique";
serviceInstaller.StartType = ServiceStartMode.Manual;
//# This must be identical to the WindowsService.ServiceBase name
//# set in the constructor of WindowsService.cs
serviceInstaller.ServiceName = "Practique";
//S.Nsibande - Add service description.
serviceInstaller.Description = "Practique - application is for testing how I should send control messages to the SCM in best practice manner so as not to get stupid errors on start and stop control requests to the Microsoft OS.";
this.Installers.Add(serviceProcessInstaller);
this.Installers.Add(serviceInstaller);
}
}
}
My entry point into my service application is as follows:
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
namespace Practique
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
#if DEBUG
Service1 myService = new Service1();
myService.OnDebug();
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#else
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]{ new Service1() };
ServiceBase.Run(ServicesToRun);
#endif
}
}
}
And then the logic performed by my service is as follows:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
namespace Practique
{
//Service class inheriting from the ServiceBase class
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
public void OnDebug()
{
OnStart(null);
}
//Two required overides... OnStart() and OnStop()
protected override void OnStart(string[] args)
{
EventLog log = new System.Diagnostics.EventLog();
log.Source = "Application";
try
{
System.IO.File.Create(AppDomain.CurrentDomain.BaseDirectory + "OnStart.txt");
System.IO.File.Create(AppDomain.CurrentDomain.BaseDirectory + "Log.txt");
}
catch (Exception ex)
{
log.WriteEntry(ex.Message + ".Stack trace - " + ex.StackTrace);
if(ex.InnerException != null)
{
log.WriteEntry(ex.InnerException.Message);
}
}
}
protected override void OnStop()
{
System.IO.File.Delete(AppDomain.CurrentDomain.BaseDirectory + "OnStart.txt");
}
private void ServiceStatus()
{
// Toggle the Practique service -
// If it is started (running, paused, etc), stop the service.
// If it is stopped, start the service.
ServiceController sc = new ServiceController("Practique");
string path = AppDomain.CurrentDomain.BaseDirectory + "Log.txt";
// Open the stream and write to it.
using (FileStream fs = File.OpenWrite(path))
{
Byte[] info =
new UTF8Encoding(true).GetBytes("The Ptractique service status is currently set to " + sc.Status.ToString() + ".");
// Add some information to the file.
fs.Write(info, 0, info.Length);
}
if ((sc.Status.Equals(ServiceControllerStatus.Stopped)) || (sc.Status.Equals(ServiceControllerStatus.StopPending)))
{
// Start the service if the current status is stopped.
// Open the stream and write to it.
using (FileStream fs = File.OpenWrite(path))
{
Byte[] info =
new UTF8Encoding(true).GetBytes("Starting the Practique service...");
// Add some information to the file.
fs.Write(info, 0, info.Length);
}
sc.Start();
}
else
{
// Stop the service if its status is not set to "Stopped".
// Open the stream and write to it.
using (FileStream fs = File.OpenWrite(path))
{
Byte[] info =
new UTF8Encoding(true).GetBytes("Stopping the Practique service...");
// Add some information to the file.
fs.Write(info, 0, info.Length);
}
sc.Stop();
}
// Refresh and display the current service status.
sc.Refresh();
// Open the stream and write to it.
using (FileStream fs = File.OpenWrite(path))
{
Byte[] info =
new UTF8Encoding(true).GetBytes("The Practique service status is now set to " + sc.Status.ToString() + ".");
// Add some information to the file.
fs.Write(info, 0, info.Length);
}
}
}
}
I might have made some very stupid basic mistake, but that is all the code on my application. And on debug, it runs just fine, it does what it is expected to do. But once installed successfully using a batch file with the following instructions:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe
"C:\Programming\Test\Practique.exe"
Pause
My question which I hope will be answered by someone that has been creating and using windows services successfully for a long time, is why does my service keep causing the following error:
This is the information from event viewer after a successful install:
A service was installed in the system.
Service Name: Practique Service File Name:
"C:\Programming\Test\Practique.exe" Service Type: user mode
service Service Start Type: demand start Service Account:
LocalSystem
Then when I attempt to start the service, I get the following error in event viewer:
A timeout was reached (30000 milliseconds) while waiting for the
Practique service to connect.
And...
The Practique service failed to start due to the following error: The
service did not respond to the start or control request in a timely
fashion.
Then I also get this popup when trying to start the service:
Please tell me if my approach is wrong, have I missed a basic principle here, what have I done wrong or have I done too much. Any assistance is greatly appreciated.
(Edit) - I am compiling in Debug mode, although I have tried release mode just in case there might be a difference, but this did not help.
With the code you have you must compile in RELEASE mode to install your service: the SCM requires a response from your service that it has started before the service starts doing any work: when your service is compiled in DEBUG mode it starts working straight away, so never reports back to the SCM, thus resulting in the error.

C# IO Reading and Writing file in use error

I have a library that handles reading and writing a cache file. This library is used by a Windows Service and several instances of a console application on the same machine. The console application runs when a user logs in.
I am getting occasional IO errors saying the cache file is in use by another process. I assume that collisions are occurring between the different application instances and service trying to read and write at the same time.
Is there a way to lock the file when it is in use and force all other requests to "wait in line" to access the file?
private void SaveCacheToDisk(WindowsUser user) {
string serializedCache = SerializeCache(_cache);
//encryt
serializedCache = AES.Encrypt(serializedCache);
string path = user == null ? ApplicationHelper.CacheDiskPath() :
_registry.GetCachePath(user);
string appdata = user == null ? ApplicationHelper.ClientApplicationDataFolder() :
_registry.GetApplicationDataPath(user);
if (Directory.Exists(appdata) == false) {
Directory.CreateDirectory(appdata);
}
if (File.Exists(path) == false) {
using (FileStream stream = File.Create(path)) { }
}
using (FileStream stream = File.Open(path, FileMode.Truncate)) {
using (StreamWriter writer = new StreamWriter(stream)) {
writer.Write(serializedCache);
}
}
}
private string ReadCacheFromDisk(WindowsUser user) {
//cache file path
string path = user == null ? ApplicationHelper.CacheDiskPath() :
_registry.GetCachePath(user);
using (FileStream stream = File.Open(path, FileMode.Open)) {
using (StreamReader reader = new StreamReader(stream)) {
string serializedCache = reader.ReadToEnd();
//decrypt
serializedCache = AES.Decrypt(serializedCache);
return serializedCache;
}
}
}
Sure, you could use a mutex and permit access only when holding the mutex.
You could use a cross-process EventWaitHandle. This lets you create and use a WaitHandle that's identified across processes by name. A thread is notified when it's its turn, does some work, and then indicates it's done allowing another thread to proceed.
Note that this only works if every process/thread is referring to the same named WaitHandle.
The EventWaitHandle constructors with strings in their signature create named system synchronization events.
One option you could consider is having the console applications route their file access through the service, that way there's only one process accessing the file and you can synchronise access to it there.
One way of implementing this is by remoting across an IPC channel (and here's another example from weblogs.asp.net). We used this technique in a project for the company I work for and it works well, with our specific case providing a way for a .net WebService to talk to a Windows Service running on the same machine.
Sample based on the weblogs.asp.net example
Basically what you need to do with the code below is create a Solution, add two Console Apps (one called "Server" and the other called "Client" and one Library to it. Add a reference to the Library to both console apps, paste the code below in and add a reference to System.Runtime.Remoting to both Server & Console.
Run the Server app, then run the client app. Observe the fact that the server app has a message passed to it by the client. You can extend this to any number of messages/tasks
// Server:
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
namespace RemotingSample
{
public class Server
{
public Server()
{
}
public static int Main(string[] args)
{
IpcChannel chan = new IpcChannel("Server");
//register channel
ChannelServices.RegisterChannel(chan, false);
//register remote object
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(RemotingSample.RemoteObject),
"RemotingServer",
WellKnownObjectMode.SingleCall);
Console.WriteLine("Server Activated");
Console.ReadLine();
return 0;
}
}
}
// Client:
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
using RemotingSample;
namespace RemotingSample
{
public class Client
{
public Client()
{
}
public static int Main(string[] args)
{
IpcChannel chan = new IpcChannel("Client");
ChannelServices.RegisterChannel(chan);
RemoteObject remObject = (RemoteObject)Activator.GetObject(
typeof(RemotingSample.RemoteObject),
"ipc://Server/RemotingServer");
if (remObject == null)
{
Console.WriteLine("cannot locate server");
}
else
{
remObject.ReplyMessage("You there?");
}
return 0;
}
}
}
// Shared Library:
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
namespace RemotingSample
{
public class RemoteObject : MarshalByRefObject
{
public RemoteObject()
{
Console.WriteLine("Remote object activated");
}
public String ReplyMessage(String msg)
{
Console.WriteLine("Client : " + msg);//print given message on console
return "Server : I'm alive !";
}
}
}
Check out the TextWriter.Synchronized method.
http://msdn.microsoft.com/en-us/library/system.io.textwriter.synchronized.aspx
This should let you do this:
TextWriter.Synchronized(writer).Write(serializedCache);

Categories

Resources