how to run an exe file on release in VSTS - sharepoint

I have created a console application for fetching the SharePoint site title inside visual studio online. The url of the SharePoint site is passed along in the code, but the password needs to entered in at console window on the run-time.
Then i have defined the build definition and is able to build the solution and copy the files to the artifact.
And i configured the release definition, and i am trying to run the build-ed .exe file, but is getting the bellow error:
Unhandled Exception: System.InvalidOperationException: Cannot read keys when either application does not have a console or when console input has been redirected from a file.
PS: I have defined a variable $pass and then added it in the arguments section for getting the password of the SharePoint site.
variable declaration:
Error Screen which i am getting:
Code for the console app:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using Microsoft.SharePoint.Client;
namespace VSTS_Demo_App
{
class Program
{
static void Main(string[] args)
{
string userName = "$$$#$$$.onmicrosoft.com";
Console.WriteLine("Enter your password.");
SecureString password = GetPassword();
// ClienContext - Get the context for the SharePoint Online Site
// SharePoint site URL - https://c986.sharepoint.com
using (var clientContext = new ClientContext("https://$$$$$$$$$$$$$$$$$$$$$$$$$$"))
{
// SharePoint Online Credentials
clientContext.Credentials = new SharePointOnlineCredentials(userName, password);
// Get the SharePoint web
Web web = clientContext.Web;
// Load the Web properties
clientContext.Load(web);
// Execute the query to the server.
clientContext.ExecuteQuery();
// Web properties - Display the Title and URL for the web
Console.WriteLine("Title: " + web.Title + "; URL: " + web.Url);
Console.ReadLine();
}
}
private static SecureString GetPassword()
{
ConsoleKeyInfo info;
Console.WriteLine("get passwod -called");
//Get the user's password as a SecureString
SecureString securePassword = new SecureString();
do
{
info = Console.ReadKey(true);
if (info.Key != ConsoleKey.Enter)
{
securePassword.AppendChar(info.KeyChar);
}
}
while (info.Key != ConsoleKey.Enter);
return securePassword;
}
}
}

The problem is with you Console.ReadLine() methods.
When running a build, vsts redirects the console input and output.
Your code is breaking here info = Console.ReadKey(true);, based on the stack trace you provided.
You are passing it via args, but you are not using it.
Change your code to:
SecureString password;
if (args.length > 0)
{
password = args;
}
else
{
password = GetPassword();
}
I didn't test if password = args will work directly or if you need to append chars. That I will leave to you.

Update your code like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using Microsoft.SharePoint.Client;
namespace VSTS_Demo_App
{
class Program
{
static void Main(string[] args)
{
string userName = "$$$#$$$.onmicrosoft.com";
Console.WriteLine("Enter your password.");
SecureString password = GetPassword(args);
// ClienContext - Get the context for the SharePoint Online Site
// SharePoint site URL - https://c986.sharepoint.com
using (var clientContext = new ClientContext("https://$$$$$$$$$$$$$$$$$$$$$$$$$$"))
{
// SharePoint Online Credentials
clientContext.Credentials = new SharePointOnlineCredentials(userName, password);
// Get the SharePoint web
Web web = clientContext.Web;
// Load the Web properties
clientContext.Load(web);
// Execute the query to the server.
clientContext.ExecuteQuery();
// Web properties - Display the Title and URL for the web
Console.WriteLine("Title: " + web.Title + "; URL: " + web.Url);
//Console.ReadLine();
}
}
private static SecureString GetPassword(string[] args)
{
ConsoleKeyInfo info;
Console.WriteLine("get passwod -called");
//Get the user's password as a SecureString
SecureString securePassword = new SecureString();
if (args.length > 0)
{
char[] cs= args[0].ToCharArray();
foreach(char c in cs)
{
securePassword.AppendChar(c);
}
}
else
{
do
{
info = Console.ReadKey(true);
if (info.Key != ConsoleKey.Enter)
{
securePassword.AppendChar(info.KeyChar);
}
}
while (info.Key != ConsoleKey.Enter);
}
return securePassword;
}
}
}

Related

SharePoint Online CSOM

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using Microsoft.SharePoint.Client;
namespace Testmyproject
{
class Program
{
static void Main(string[] args)
{
string userName = "pratapbangosavi#xqsnt.onmicrosoft.com";
Console.WriteLine("Enter Your Password Please ------- ");
SecureString password = GetPasswordOfYourSite();
// ClienContext - Get the context for the SharePoint Online Site
using (var clientContext = new
ClientContext("https://xqsnt.sharepoint.com/sites/mysite/"))
{
// SharePoint Online Credentials
clientContext.Credentials = new SharePointOnlineCredentials(userName, password);
// Get the SharePoint web
Web web = clientContext.Web;
// Load the Web properties
clientContext.Load(web);
// Execute the query to the server.
clientContext.ExecuteQuery();
// Web properties - Display the Title and URL for the web
Console.WriteLine("Title: " + web.Title);
Console.WriteLine("URL: " + web.Url);
Console.WriteLine("Template: " + web.WebTemplate);
Console.ReadLine();
}
}
private static SecureString GetPasswordOfYourSite()
{
ConsoleKeyInfo info;
//Get the user's password as a SecureString
SecureString securePassword = new SecureString();
do
{
info = Console.ReadKey(true);
if (info.Key != ConsoleKey.Enter)
{
securePassword.AppendChar(info.KeyChar);
}
}
while (info.Key != ConsoleKey.Enter);
return securePassword;
}
}
}
If you are trying to run CSOM against SharePoint Online and gets the error below.
All Contents are correct as like Site URL, Username and password.
I need to display SharePoint Site Title, URL and Template but show Error at clientContext.ExecuteQuery();
enter image description here
Please check your .NET Framework version. Please change the version to 4.6 or later to resolve this issue. If you are using .NET Framework under 4.6. You can add the following code to resolve this issue:
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
Hope it can help you. Thanks for your understanding.

Azure Cognitive Service\Computer Visio\OCR - Can I use it into into WebSite C#

I'm trying to use Azure Ocr into my website c#.
I added the package Microsoft.Azure.CognitiveServices.Vision.ComputerVision and I wrote code, with key and endpoint of my subscription.
static string subscriptionKey = "mykey";
static string endpoint = "https://myocr.cognitiveservices.azure.com/";
private const string ANALYZE_URL_IMAGE = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/ComputerVision/Images/printed_text.jpg";
protected void Page_Load(object sender, EventArgs e)
{
// Create a client
ComputerVisionClient client = Authenticate(endpoint, subscriptionKey);
// Analyze an image to get features and other properties.
AnalyzeImageUrl(client, ANALYZE_URL_IMAGE).Wait();
}
public static ComputerVisionClient Authenticate(string endpoint, string key)
{
ComputerVisionClient client =
new ComputerVisionClient(new ApiKeyServiceClientCredentials(key))
{ Endpoint = endpoint };
return client;
}
public static async Task AnalyzeImageUrl(ComputerVisionClient client, string imageUrl)
{
// Read text from URL
var textHeaders = await client.ReadAsync(imageUrl);
...
}
It seems all ok, but at line
var textHeaders = await client.ReadAsync(urlFile);
website crashes.
I don't understand why. No error, it's just stopped.
So I ask: azure ocr can to be use only with console app?
EDIT
The code is ok for ConsoleApp and WebApp but not working for my asp.net WEBSITE.
Could be a problem with async?
We can use OCR with web app also,I have taken the .net core 3.1 webapp in Visual Studio and installed the dependency of Microsoft.Azure.CognitiveServices.Vision.ComputerVision by selecting the check mark of include prerelease as shown in the below image:
After creating computer vision resource in Azure Portal, copied the key and endpoint from there and used inside the c# code.
using System;
using System.Collections.Generic;
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision;
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision.Models;
using System.Threading.Tasks;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Threading;
using System.Linq;
namespace ComputerVisionQuickstart
{
class Program
{
// Add your Computer Vision subscription key and endpoint
static string subscriptionKey = "c1****b********";
static string endpoint = ".abc.cognitiveservices.azure.com/";
private const string READ_TEXT_URL_IMAGE = "https://raw.githubusercontent.com/Azure-Samples/cognitive-services-sample-data-files/master/ComputerVision/Images/printed_text.jpg";
static void Main(string[] args)
{
Console.WriteLine("Azure Cognitive Services Computer Vision - .NET quickstart example");
Console.WriteLine();
ComputerVisionClient client = Authenticate(endpoint, subscriptionKey);
// Extract text (OCR) from a URL image using the Read API
ReadFileUrl(client, READ_TEXT_URL_IMAGE).Wait();
}
public static ComputerVisionClient Authenticate(string endpoint, string key)
{
ComputerVisionClient client =
new ComputerVisionClient(new ApiKeyServiceClientCredentials(key))
{ Endpoint = endpoint };
return client;
}
public static async Task ReadFileUrl(ComputerVisionClient client, string urlFile)
{
Console.WriteLine("----------------------------------------------------------");
Console.WriteLine("READ FILE FROM URL");
Console.WriteLine();
// Read text from URL
var textHeaders = await client.ReadAsync(urlFile);
// After the request, get the operation location (operation ID)
string operationLocation = textHeaders.OperationLocation;
Thread.Sleep(2000);
// Retrieve the URI where the extracted text will be stored from the Operation-Location header.
// We only need the ID and not the full URL
const int numberOfCharsInOperationId = 36;
string operationId = operationLocation.Substring(operationLocation.Length - numberOfCharsInOperationId);
// Extract the text
ReadOperationResult results;
Console.WriteLine($"Extracting text from URL file {Path.GetFileName(urlFile)}...");
Console.WriteLine();
do
{
results = await client.GetReadResultAsync(Guid.Parse(operationId));
}
while ((results.Status == OperationStatusCodes.Running ||
results.Status == OperationStatusCodes.NotStarted));
// Display the found text.
Console.WriteLine();
var textUrlFileResults = results.AnalyzeResult.ReadResults;
foreach (ReadResult page in textUrlFileResults)
{
foreach (Line line in page.Lines)
{
Console.WriteLine(line.Text);
}
}
Console.WriteLine();
}
}
}
The above code is taken from the Microsoft Document.
I can be able to read the text inside the image successfully as shown in the below screenshot:

I am no longer able to debug/run my SharePoint Remote Event Receiver locally using Ngrok

Last month the below steps were working well for me to debug and test a SharePoint online remote event receiver locally:-
Open Ngrok.exe >> run the following command inside ngrok:-
ngrok authtoken 3***e
ngrok http --host-header=rewrite 57269
register a new app:- # https://.sharepoint.com/sites//_layouts/15/AppRegNew.aspx >> enter the above Ngrok urls inside the App Redirect URL & App Domain.
Inside the _layouts/15/appinv.aspx >> I search for the above app using Client ID >> and enter the following:-
<AppPermissionRequests AllowAppOnlyPolicy="true">
<AppPermissionRequest Scope="http://sharepoint/content/tenant" Right="FullControl" />
</AppPermissionRequests>
Update the service's web config with the above ClientID and ClientSecret
Register the new remove event receiver as follow:-
Add-PnPEventReceiver -List "Order Management" -Name "TasksRER" -Url http://cc6e945e82f6.ngrok.io/service1.svc -EventReceiverType ItemUpdated -Synchronization Asynchronous
But today when I tried the above steps it failed >> where inside my event receiver when I tried to get the SharePoint context >> I will get that the Context is null:-
public void ProcessOneWayEvent(SPRemoteEventProperties properties)
{
var prop = properties;
var listItemID = properties.ItemEventProperties.ListItemId;
var listTitle = properties.ItemEventProperties.ListTitle;
using (ClientContext context = Helpers.GetAppOnlyContext(properties.ItemEventProperties.WebUrl))
{
context.Load(context.Web);
context.ExecuteQuery();
Here is a screen shot from Visual Studio with the error i am getting when trying to get the context:-
Any advice if anything has been changed which is preventing me from running the above steps? which were working well last month?
Thanks
here is the code for the GetAppOnlyContext
public class Helpers
{
public static ClientContext GetAppOnlyContext(string siteUrl)
{
try
{
Uri siteUri = new Uri(siteUrl);
string realm = TokenHelper.GetRealmFromTargetUrl(siteUri);
string accessToken = TokenHelper.GetAppOnlyAccessToken(TokenHelper.SharePointPrincipal, siteUri.Authority, realm).AccessToken;
return TokenHelper.GetClientContextWithAccessToken(siteUri.ToString(), accessToken);
}
catch (Exception ex)
{
Trace.TraceInformation("GetAppOnlyContext failed. {0}", ex.Message);
}
return null;
}
public static ClientContext GetAuthenticatedContext(string siteUrl)
{
string userName = WebConfigurationManager.AppSettings.Get("AuthenticatedUserName");
string password = WebConfigurationManager.AppSettings.Get("AuthenticatedUserPassword");
return GetAuthenticatedContext(siteUrl, userName, password);
}
public static ClientContext GetAuthenticatedContext(string siteUrl, string userName, SecureString password)
{
ClientContext ctx = new ClientContext(siteUrl);
ctx.Credentials = new SharePointOnlineCredentials(userName, password);
return ctx;
}
public static ClientContext GetAuthenticatedContext(string siteUrl, string userName, string password)
{
SecureString securePassword = GetPassword(password);
return GetAuthenticatedContext(siteUrl, userName, securePassword);
}
private static SecureString GetPassword(string passwd)
{
var secure = new SecureString();
foreach (char c in passwd)
{
secure.AppendChar(c);
}
return secure;
}
public static string EmptyIfNull(object obj)
{
return obj == null ? "" : obj.ToString();
}
}
}

Getting NULL terms when accesing TermCollection from SharePoint Online via CSOM in an Azure Function

I am trying to expose a REST API using Azure Functions which returns terms from a specific termset in SharePoint Online using CSOM and C#.
I can definitely invoke this exact same CSOM code from a console app and from an Azure API app and it is able to loop through the terms and output to console or the HTTP response successfully.
However, when the code below is invoked from the Azure Function host, it ALWAYS find a collection of NULL term objects, when looping through the TermCollection or the IEnumerable<Term> (I’ve tried by using ClientContext.LoadQuery on TermSet.GetAllTerms(), as well as by just loading the TermCollection via the TermSet.Terms property).
As soon as the iterator hits a term in the foreach (which I’ve also tried as just a LINQ Select), it thinks that the item is NULL, so calling properties on it throws the NullReferenceException. I cannot reproduce the behavior from the console app or from the API app calling into the same code - it just works as expected there and retrieves each Term object.
Why is this happening when SAME CODE is invoked from different hosts??
Why would this happen in the Azure Functions host, but not in Console app or the Azure API app?
What is the difference when invoked from an Azure Function host??
I would really like to use Azure Functions for the consumption pricing benefits, so I don't have to host this in an App Service.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.Taxonomy;
namespace CsomTaxonomyHelper
{
public class TermSearch
{
private readonly ClientContext ctx;
public TermSearch(ClientContext context)
{
if (context == null)
throw new ArgumentNullException(nameof(context));
ctx = context;
}
public IEnumerable<TermViewModel> GetTerms(Guid termSetId)
{
var taxonomySession = TaxonomySession.GetTaxonomySession(ctx);
var termStore = taxonomySession.GetDefaultSiteCollectionTermStore();
var termSet = termStore.GetTermSet(termSetId);
//get flat list of terms, so we don't make recursive calls to SPO
var allTerms = ctx.LoadQuery(termSet.GetAllTerms().IncludeWithDefaultProperties());
ctx.ExecuteQuery();
return ToViewModel(allTerms);
}
static IEnumerable<TermViewModel> ToViewModel(IEnumerable<Term> allTerms)
{
var results = allTerms.Select(term => new TermViewModel
{
Id = term.Id, //BOOM! <-- within the context of an Azure Function the "allTerms" IEnumerable is a list of nulls
Name = term.Name,
ParentId = TryGetParentId(term)
});
return results;
}
static Guid? TryGetParentId(Term term)
{
try
{
if (term.Parent.IsPropertyAvailable("Id"))
return term.Parent.Id;
}
catch (ServerObjectNullReferenceException) { }
return null;
}
}
public class PasswordString
{
public SecureString SecurePassword { get; private set; }
public PasswordString(string password)
{
SecurePassword = new SecureString();
foreach (char c in password.ToCharArray())
{
SecurePassword.AppendChar(c);
}
SecurePassword.MakeReadOnly();
}
}
}
Here's the "run.csx" function, invoking the code above which has been compiled into a DLL and placed in the Bin folder of the Azure Function:
#r "CsomTaxonomyHelper.dll"
#r "Newtonsoft.Json"
using System.Net;
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.Taxonomy;
using CsomTaxonomyHelper;
using Newtonsoft.Json;
static TraceWriter _log = null;
public static HttpResponseMessage Run(HttpRequestMessage req, TraceWriter log)
{
_log = log;
_log.Info("C# HTTP trigger function processed a request. Getting mmd terms from SPO...");
var terms = GetFocusAreas();
var result = JsonConvert.SerializeObject(terms);
return req.CreateResponse(HttpStatusCode.OK, result);
}
static IEnumerable<TermViewModel> GetFocusAreas()
{
string spSiteUrl = System.Environment.GetEnvironmentVariable("SPOSiteUrl", EnvironmentVariableTarget.Process);
string userName = System.Environment.GetEnvironmentVariable("SPOUserName", EnvironmentVariableTarget.Process);
string password = System.Environment.GetEnvironmentVariable("SPOPassword", EnvironmentVariableTarget.Process);
var securePwd = new PasswordString(password).SecurePassword;
using (var ctx = new ClientContext(spSiteUrl))
{
ctx.Credentials = new SharePointOnlineCredentials(userName, securePwd);
ctx.ExecuteQuery();
_log.Info("Logged into SPO service.");
var search = new TermSearch(ctx);
try
{
var result = search.GetTerms(new Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"));
return result;
}
catch (Exception ex)
{
_log.Error(ex.Message, ex);
throw;
}
}
}
Project.json:
{
"frameworks": {
"net46":{
"dependencies": {
"Microsoft.SharePointOnline.CSOM": "16.1.6112.1200"
}
}
}
}
Here's the screenshot of the local debugger, when using the Azure Functions CLI to debug this (you can see that it did find 10 items in the collection, but all items are null):
Not the solution, but adding to the conversation - I was able to test with PnP-PowerShell (2017-Feb). Terms were just added.
SPO, CSOM and PnP-PowerShell.
Installing PnP-PowerShell to a PowerShell function:

Sharepoint: How do i find a mail enabled list, if i only have the email?

I know the email from a mail enabled list, with I have no idea where the list lies.
How do i find the list to which the email belongs to?
The code below works if you know the site collection of the list. If you don't know that, you can easily modify the code to loop a complete web application (or even a complete farm):
using System;
using Microsoft.SharePoint;
namespace FindListByEmail
{
class Program
{
static void Main(string[] args)
{
string siteUrl = "[complete this]";
string email = "[complete this]"; // only the part before the #
using (SPSite site = new SPSite(siteUrl))
{
foreach (SPWeb web in site.AllWebs)
{
try
{
foreach (SPList list in web.Lists)
{
if (list.CanReceiveEmail)
{
if (list.EmailAlias != null && list.EmailAlias.Equals(email, StringComparison.InvariantCultureIgnoreCase))
{
Console.WriteLine("The email belongs to list {0} in web {1}", list.Title, web.Url);
Console.ReadLine();
return;
}
}
}
}
finally
{
if (web != null)
{
web.Dispose();
}
}
}
}
}
}
}
To find All Incoming E-Mail Enabled Lists and Libraries in SharePoint, You can use PowerShell , C# code or SQL Server Query!
Find the PowerShell Script, SQL Query and C# code here: http://www.sharepointdiary.com/2011/06/find-all-incoming-email-enabled-lists.html#ixzz2aKvhRTDN

Resources