[solved] Need some advices in .net

DonManfred

Expert
Licensed User
Longtime User
I´m trying to build a solution to upload Videos on youtube.
In java i got stuck. The provided java codes by google are from 2012.
Then i check .net. Here the sources are from this year.
I instaled Microsoft visual Studio Community 2017
And in a few minutes i got a version running to post a Youtube video id to a specific playlist.
Fine, works. But totally hardcoded...

I want it to use it like a commandlinetool.

My problem is now to know how i get a commandlinearg to a variable inside the app an specificially on how to get these variables to the thread i start here....

A example

B4X:
/*
* Copyright 2015 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*
*/

using System;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;

using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.Upload;
using Google.Apis.Util.Store;
using Google.Apis.YouTube.v3;
using Google.Apis.YouTube.v3.Data;

namespace Google.Apis.YouTube.Samples
{
  /// <summary>
  /// YouTube Data API v3 sample: upload a video.
  /// Relies on the Google APIs Client Library for .NET, v1.7.0 or higher.
  /// See https://code.google.com/p/google-api-dotnet-client/wiki/GettingStarted
  /// </summary>
  internal class UploadVideo {
    private string title;
    private string description;

    [STAThread]
    static void Main(string[] args) {
      //UploadVideo.Main.title = "t";
      //Description = "Default Video Description";
      foreach (var e in args) {
        Console.WriteLine("Arg: " + e); ' i know this will prompt the commandlineargs... i want to use them inside the app to set the variables "title" and "description" which should be used inside the thread "UploadVideo().Run()"
      }
      Console.WriteLine("YouTube Data API: Upload Video");
      Console.WriteLine("==============================");

      try
      {
        new UploadVideo().Run().Wait();
      }
      catch (AggregateException ex)
      {
        foreach (var e in ex.InnerExceptions)
        {
          Console.WriteLine("Error: " + e.Message);
        }
      }

      Console.WriteLine("Press any key to continue...");
      Console.ReadKey();
    }

    private async Task Run()
    {
      UserCredential credential;
      using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
      {
        credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
            GoogleClientSecrets.Load(stream).Secrets,
            // This OAuth 2.0 access scope allows an application to upload files to the
            // authenticated user's YouTube channel, but doesn't allow other types of access.
            new[] { YouTubeService.Scope.YoutubeUpload },
            "user",
            CancellationToken.None
        );
      }


      var youtubeService = new YouTubeService(new BaseClientService.Initializer()
      {
        HttpClientInitializer = credential,
        ApplicationName = Assembly.GetExecutingAssembly().GetName().Name
      });

      var video = new Video();
      video.Snippet = new VideoSnippet();
      video.Snippet.Title = title;
      video.Snippet.Description = description;
      video.Snippet.Tags = new string[] { "tag1", "tag2" };
      video.Snippet.CategoryId = "22"; // See https://developers.google.com/youtube/v3/docs/videoCategories/list
      video.Status = new VideoStatus();
      video.Status.PrivacyStatus = "unlisted"; // or "private" or "public"
      var filePath = @"REPLACE_ME.mp4"; // Replace with path to actual movie file.

      using (var fileStream = new FileStream(filePath, FileMode.Open))
      {
        var videosInsertRequest = youtubeService.Videos.Insert(video, "snippet,status", fileStream, "video/*");
        videosInsertRequest.ProgressChanged += videosInsertRequest_ProgressChanged;
        videosInsertRequest.ResponseReceived += videosInsertRequest_ResponseReceived;

        await videosInsertRequest.UploadAsync();
      }
    }

    void videosInsertRequest_ProgressChanged(Google.Apis.Upload.IUploadProgress progress)
    {
      switch (progress.Status)
      {
        case UploadStatus.Uploading:
          Console.WriteLine("{0} bytes sent.", progress.BytesSent);
          break;

        case UploadStatus.Failed:
          Console.WriteLine("An error prevented the upload from completing.\n{0}", progress.Exception);
          break;
      }
    }

    void videosInsertRequest_ResponseReceived(Video video)
    {
      Console.WriteLine("Video id '{0}' was successfully uploaded.", video.Id);
    }
  }
}

The interesting line (my question) is here

B4X:
Console.WriteLine("Arg: " + e); '

i know this will prompt the commandlineargs... i want to use them inside the app to set the variables "title" and "description" which should be used inside the thread "UploadVideo().Run()"


Any hints or tips how to do this i would really appreciate :)
 

OliverA

Expert
Licensed User
Longtime User
i know this will prompt the commandlineargs... i want to use them inside the app to set the variables "title" and "description" which should be used inside the thread "UploadVideo().Run()"


Any hints or tips how to do this i would really appreciate

Note: I'm not a .NET programmer (in any form or fashion)

Since args is just an array that contains your command line arguments, you can

1) Just run the command with the parameters in a specific sequence. For example:

yournetprogram thisfile thistitle thisdescription

and then

args[0] would contain thisfile
args[1] would contain thistitle
args[2] would contain thisdescription

You can assign these to variables/pass them on to other functions/methods.

2) You can use a library to handle your command line parameters. That would allow you to use out of order parameters, account for missing parameters with defaults, etc. One such library may be: https://commandline.codeplex.com/
 

DonManfred

Expert
Licensed User
Longtime User
Another way which might be easier is to use PowerShell, you could create your own cmdlet the way you want it.
but for this i would need a possibility to do XY via comandline (or not?).... As of now i do not have it and i´m trying to build a solution based on the .net code above...

Globally said i have it running but i need to understand a bit more about .net to extend it to my needs...

For now it is not much; i need to know how to parse the comandlineargs and to assign them to class variables which should be used by the thread (variables are not modified in the thread. The thread just need them to set the title and description in the api-call... and the filename of the video for sure) when it runs...
 

sorex

Expert
Licensed User
Longtime User
the commandline arguments are assigned to an array.

if I recall right they belong to the main environments so it's something like

"mytool url"

url=environment.getcommandlineargs(0)

make sure you check the lenght first otherwise you app will crash if you don't pass a parameter
 

DonManfred

Expert
Licensed User
Longtime User
I got it working this way...


I defined some vars inside the main-block.
I assigned the commands to the variables
And then i extended the Thread-signature to add them in the call....
Inside the thread i get them as variables given and i can use them to set the properties....

B4X:
    static void Main(string[] args) {
            string filename = "";
      string tag1 = "";
      string tag2 = "";
      string title = "";
      string desc = "";
            int pos = 0;
            foreach (var e in args) {
                pos += 1;
        if (pos == 1){
                    filename = e;
                }
                if (pos == 2){
                    tag1 = e;
                }
                if (pos == 3){
                    tag2 = e;
                }
                if (pos == 4){
                    title = e;
                }
                if (pos == 5){
                    desc = e;
                }
                Console.WriteLine("Arg"+pos+": " + e);
      }
      Console.WriteLine("YouTube Data API: Upload Video");
      Console.WriteLine("==============================");
      Console.WriteLine("Filename = "+filename);
      Console.WriteLine("Tag1   = " + tag1);
      Console.WriteLine("Tag2   = " + tag2);
      Console.WriteLine("Title  = " + title);
            Console.WriteLine("Descr. = " + desc);
               
      try{
        new UploadVideo().Run(filename, tag1, tag2, title, desc).Wait();
      } catch (AggregateException ex){
        foreach (var e in ex.InnerExceptions) {
          Console.WriteLine("Error: " + e.Message);
        }
      }
 

JakeBullet70

Well-Known Member
Licensed User
Longtime User
Take a look at this code. I use flags so position is not an issue. This way also allows you to add quotes to your file names - paths as there can be an issue there.

B4X:
Private Sub AutoModeCheckAndSetOnStartup()

      Dim cmdargs As String() = Environment.GetCommandLineArgs()
      For Each arg In cmdargs
      
         If arg.ToUpper.Contains("EMAIL:") Then
            EmailAddress = arg.ToUpper.Replace("EMAIL:", "")
         End If
         If arg.ToUpper.Contains("FILENAME:") Then
            MyFilename = arg.ToUpper.Replace("FILENAME:", "")
         End If
         If arg.ToUpper.Contains("TAG1:") Then
            MyTag1 = arg.ToUpper.Replace("TAG1:", "")
         End If

      Next

   End Sub
 
Top