.NET ShareFileItem properties null for Azure File Share - c#

I am trying to create an azure function that'll clear down files older than a certain age, but when I access the properties of the file they are all null, what am I doing wrong?!
using System;
using System.Collections.Generic;
using Azure.Storage.Files.Shares;
using Azure.Storage.Files.Shares.Models;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
namespace somewhere
{
public static class FileShareCleaner
{
[FunctionName("FileShareCleaner")]
public static void Run([TimerTrigger("*/10 */1 * * * *")]TimerInfo myTimer, ILogger log)
{
string connectionString = Environment.GetEnvironmentVariable("FileShareConnectionString");
string shareName = "files";
ShareServiceClient shareserviceclient = new ShareServiceClient(connectionString);
ShareClient shareclient = shareserviceclient.GetShareClient(shareName);
Queue<ShareDirectoryClient> remaining = new Queue<ShareDirectoryClient>();
remaining.Enqueue(shareclient.GetRootDirectoryClient());
while (remaining.Count > 0)
{
ShareDirectoryClient dir = remaining.Dequeue();
foreach (ShareFileItem item in dir.GetFilesAndDirectories())
{
log.LogInformation(item.Name);
if (item.IsDirectory)
{
remaining.Enqueue(dir.GetSubdirectoryClient(item.Name));
}
else
{
log.LogInformation($"time: {item.Properties.LastModified.ToString()}");
}
}
}
}
}
}
The code finds the files but all the properties are null:
[2021-10-06T10:04:50.048Z] Executing 'FileShareCleaner' (Reason='Timer fired at 2021-10-06T11:04:50.0126493+01:00', Id=af5c7864-4326-4c97-b9d6-82bf98726f4e)
[2021-10-06T10:04:50.341Z] 0304ccf5-4e32-4206-b903-af5acc8652dc.dat
[2021-10-06T10:04:50.344Z] time:
[2021-10-06T10:04:50.347Z] 06716b40-cce4-4ef0-86ec-329dcaeddbf4.dat
[2021-10-06T10:04:50.350Z] time:
[2021-10-06T10:04:50.353Z] 20735b83-d8b2-4110-9ee6-6154b97c154c.dat
[2021-10-06T10:04:50.355Z] time:
[2021-10-06T10:04:50.358Z] 2696a0eb-2aed-4200-b495-0dd2a7152139.dat
[2021-10-06T10:04:50.361Z] time:

You are not doing anything wrong. This is expected behavior.
By default when files and folders are listed in a File Share, only size of the file is returned.
For fetching other properties of the file like last modified or content properties, you will need to get the properties of each file separately.
Update
To get the properties, what you will need to do is create an instance of ShareFileClient using ShareDirectoryClient.GetFileClient and then call GetProperties on that. Your code would look something like below:
while (remaining.Count > 0)
{
ShareDirectoryClient dir = remaining.Dequeue();
foreach (ShareFileItem item in dir.GetFilesAndDirectories())
{
log.LogInformation(item.Name);
if (item.IsDirectory)
{
remaining.Enqueue(dir.GetSubdirectoryClient(item.Name));
}
else
{
var fileClient = dir.GetFileClient(item.Name);
var fileProperties = fileClient.GetProperties();
log.LogInformation($"time: {fileProperties.Value.LastModified.ToString()}");
}
}
}

Related

Get literal system variable path

Is there any way to get the path environmental variable as a literal string instead of expanded?
i.e.
%systemroot%\System32;%systemroot%\;etc...
instead of
C:\Windows\System32;C:\Windows\;etc...
I've tried using
Environment.GetSystemVariable("Path");
But that gives me the expanded directories and I don't see anything else under Environment that will get me that.
Edit:
PathUnExpandEnvStrings only works if the entire path is an environmental variable.
i.e.
C:\Windows\System32;C:\Windows;etc...
becomes
C:\Windows\System32;%systemroot%;etc...
using
Registry.GetValue(#"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment", "Path", null);
Still gets the values as C:\Windows\System32;C:\Windows;etc...
If you go the registry route you can pass RegistryValueOptions.DoNotExpandEnvironmentNames to the RegistryKey.GetValue() instance method to get the unexpanded path...
using System;
using Microsoft.Win32;
namespace SO60725684
{
class Program
{
static void Main()
{
const string environmentKeyPath = #"SYSTEM\CurrentControlSet\Control\Session Manager\Environment";
const string valueName = "TEMP";
using (RegistryKey environmentKey = Registry.LocalMachine.OpenSubKey(environmentKeyPath))
{
foreach (RegistryValueOptions options in Enum.GetValues(typeof(RegistryValueOptions)))
{
object valueData = environmentKey.GetValue(valueName, "<default>", options);
Console.WriteLine($"{valueName} ({options}) = \"{valueData}\"");
}
}
}
}
}
This prints...
Temp (None) = "C:\WINDOWS\TEMP"
Temp (DoNotExpandEnvironmentNames) = "%SystemRoot%\TEMP"
I'm using the "TEMP" variable just for the brevity of its value, but it works just as well for "Path".
If you don't want to rely on the backing storage of an environment variable, there is also a Win32_Environment management class that exposes the value without expansion...
using System;
using System.Management;
namespace SO60725684
{
class Program
{
static void Main()
{
string[] propertiesToDisplay = new string[] { "Name", "SystemVariable", "UserName", "VariableValue" };
ObjectQuery query = new SelectQuery("Win32_Environment", "Name = 'TEMP'", propertiesToDisplay);
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query))
using (ManagementObjectCollection resultCollection = searcher.Get())
{
foreach (ManagementBaseObject resultInstance in resultCollection)
{
PropertyDataCollection properties = resultInstance.Properties;
foreach (string propertyName in propertiesToDisplay)
{
PropertyData property = properties[propertyName];
Console.WriteLine($"{property.Name}: {property.Value}");
}
Console.WriteLine();
}
}
}
}
}
This prints...
Name: TEMP
SystemVariable: True
UserName: <SYSTEM>
VariableValue: %SystemRoot%\TEMP
Name: TEMP
SystemVariable: False
UserName: NT AUTHORITY\SYSTEM
VariableValue: %USERPROFILE%\AppData\Local\Temp
Name: TEMP
SystemVariable: False
UserName: ComputerName\UserName
VariableValue: %USERPROFILE%\AppData\Local\Temp
As you can see, you get multiple results when the variable is defined for multiple users, so you'll need to do further filtering on the SystemVariable and UserName properties to get the one you want.

How to download files from Folders inside Azure Blob storage? [duplicate]

I'm new to Azure and playing around with blobs in my .Net application.
I want to be able to get structure with folders, subfolders and files inside.
For now I've figured a way to get the files from all folders and subfolders altogether with parents.
Is there any way to get folder structure some other way than parse Prefix of those files' parents?
File structure is the following:
root container
-folder1
-subfolder1
-file
-file
-subfolder2
-file
-file
-file
I've tried this, but it only gives me folder in the root directory, no subfolders:
//returns account, client and container
var blobData = GetBlobDetails(blobConnectionString, rootContainerName);
var rootContainer = blobData.Container;
var blobList = rootContainer.ListBlobsSegmentedAsync(string.Empty, false, BlobListingDetails.None, int.MaxValue, null, null, null);
return (from blob in blobList.Result
.Results
.OfType<CloudBlobDirectory>()
select blob).ToList();
First of all, as noted in the comments: Blob storage does not know the concept of folders. Is all a flat structure and what you see below as prefixes, is all part of the path of a blob (=file).
That said, you can replicate the behavior by traversing the prefixes:
Using Azure.Storage.Blobs 12.2.0
using Azure;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using System;
using System.Threading.Tasks;
using System.Linq;
namespace BlobLister
{
class Program
{
static async Task Main(string[] args)
{
// Get a connection string to our Azure Storage account.
string connectionString = "*****";
string containerName = "mycontainer";
Console.WriteLine($"Recursivly listing blobs and virtual directories for container '{containerName}'");
BlobContainerClient container = new BlobContainerClient(connectionString, containerName);
await ListBlobsForPrefixRecursive(container, "", 0);
}
public static async Task ListBlobsForPrefixRecursive(BlobContainerClient container, string prefix, int level)
{
string spaces = new string(' ', level);
Console.WriteLine($"{spaces}- {prefix}");
await foreach (Page<BlobHierarchyItem> page in container.GetBlobsByHierarchyAsync(prefix: prefix, delimiter: "/").AsPages())
{
foreach (var blob in page.Values.Where(item => item.IsBlob).Select(item => item.Blob))
{
Console.WriteLine($"{spaces} {blob.Name}");
}
var prefixes = page.Values.Where(item => item.IsPrefix).Select(item => item.Prefix);
foreach (var p in prefixes)
{
await ListBlobsForPrefixRecursive(container, p, level + 1);
}
}
}
}
}

Azure Function: Unzip file works in debug but not in production

This is my very first Azure function. I need to unzip a file after it is uploaded on an Azure Storage Blob.
I found this video https://www.youtube.com/watch?v=GRztpy337kU and this post: https://msdevzone.wordpress.com/2017/07/07/extract-a-zip-file-stored-in-azure-blob.
Using Visual Studio 2017 with C#, all works fine when i run the function in Visual Studio but when i deploy it to Azure, nothing is extracted. If i watch the log all seems ok.
Here is my code:
using System;
using System.IO;
using System.IO.Compression;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.WindowsAzure.Storage;
namespace ExtractZipFunction
{
public static class ScompattaZip
{
[FunctionName("ScompattaZip")]
public static void Run([BlobTrigger("input-files/{name}", Connection = "connectionStorage")]
Stream myBlob, string name, TraceWriter log)
{
log.Info($"C# Blob trigger function Processed blob\n Name:{name} \n Size: {myBlob.Length} Bytes");
try
{
string destinationStorage = Environment.GetEnvironmentVariable("destinationStorage");
string destinationContainer = Environment.GetEnvironmentVariable("destinationContainer");
log.Info($"destinationStorage: {destinationStorage}");
log.Info($"destinationContainer: {destinationContainer}");
if (System.IO.Path.GetExtension(name).ToLower() == ".zip")
{
log.Info("It's a zip");
var archive = new ZipArchive(myBlob);
var storageAccount = CloudStorageAccount.Parse(destinationStorage);
var blobClient = storageAccount.CreateCloudBlobClient();
var container = blobClient.GetContainerReference(destinationContainer);
foreach (var entry in archive.Entries)
{
var blockBlob = container.GetBlockBlobReference(entry.FullName);
using (var fileStream = entry.Open())
{
if (entry.Length > 0)
{
log.Info($"Estrazione 1 - {entry.FullName}");
blockBlob.UploadFromStreamAsync(fileStream);
log.Info($"Estrazione 2 - {entry.FullName}");
}
}
}
}
else
log.Info("Not a zip");
}
catch (Exception ex)
{
log.Info($"Errore: {ex.Message}");
}
}
}
}
And this is the log in Azure:
C# Blob trigger function Processed blob
Name:EmptyJSONFile_1033.zip
Size: 24294 Bytes
destinationStorage: DefaultEndpointsProtocol=https;AccountName=[...]
destinationContainer: outputfiles
E' uno zip
Estrazione EmptyJSONFile_1033.ico
Estrazione 1 - EmptyJSONFile_1033.ico
Estrazione 2 - EmptyJSONFile_1033.ico
Estrazione EmptyJSONFile_1033.vstemplate
Estrazione 1 - EmptyJSONFile_1033.vstemplate
Estrazione 2 - EmptyJSONFile_1033.vstemplate
Estrazione json.json
Estrazione 1 - json.json
Estrazione 2 - json.json
All seems OK but at the end of the function the container outputfiles is empty!
What am I doing wrong?
Except for my comment above (please do this anyway!), you issue is here:
blockBlob.UploadFromStreamAsync(fileStream);
it needs to be instead:
await blockBlob.UploadFromStreamAsync(fileStream);
and your function itself:
public static async Task Run([BlobTrigger("input-files/{name}", Connection = "connectionStorage")] Stream myBlob, string name, TraceWriter log)
//Edit: So here is a full example using output bindings. Note that you can of course also use two different connection strings (two different storage accounts) for trigger and output binding if you like to.
using System;
using System.IO;
using System.IO.Compression;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
using Microsoft.WindowsAzure.Storage.Blob;
namespace SampleFunctions
{
public static class UnzipBlob
{
/// <summary>
/// This function is triggered by new blobs (should be a ZIP file)
/// and extracts the contents of the zip as new, individual blobs to a storage account
/// </summary>
/// <param name="inputBlob"></param>
/// <param name="inputBlobName"></param>
/// <param name="outputContainer"></param>
/// <param name="log"></param>
/// <returns></returns>
[FunctionName("UnzipBlob")]
public static async Task Run([BlobTrigger("input-zips/{inputBlobName}", Connection = "AzureWebJobsStorage")] Stream inputBlob, string inputBlobName,
Binder binder,
ILogger log)
{
log.LogInformation($"Blob trigger function received blob\n Name:{inputBlobName} \n Size: {inputBlob.Length} Bytes");
if (Path.GetExtension(inputBlobName)?.ToLower() == ".zip")
{
// We use the first char of the input file name as a dynamic part in the container. (Note: You should check if this is a valid char for the container name)
var container = $"my-dynamic-container-{inputBlobName.Substring(0,1).ToLower()}";
var attributes = new Attribute[]
{
new BlobAttribute($"{container}", FileAccess.ReadWrite),
new StorageAccountAttribute("AzureWebJobsStorage")
};
var outputContainer = await binder.BindAsync<CloudBlobContainer>(attributes);
await outputContainer.CreateIfNotExistsAsync();
var archive = new ZipArchive(inputBlob);
foreach (var entry in archive.Entries)
{
// we write the output files to a directory with the same name as the input blob. Change as required
var blockBlob = outputContainer.GetBlockBlobReference($"{inputBlobName}/{entry.FullName}");
using (var fileStream = entry.Open())
{
if (entry.Length > 0)
{
log.LogInformation($"Extracting - {entry.FullName} to - {blockBlob.Name}");
await blockBlob.UploadFromStreamAsync(fileStream);
}
}
}
}
else
{
log.LogInformation("Not a zip file. Ignoring");
}
}
}
}

How to use the gRPC tools to generate code

I've read the tutorial and I'm able to generate the .cs file but it doesn't include any of my service or rpc definitions.
I've added protoc to my PATH and from inside the project directory.
protoc project1.proto --csharp_out="C:\output" --plugin=protoc-gen-grpc="c:\Users\me\.nuget\packages\grpc.tools\1.8.0\tools\windows_x64\grpc_csharp_plugin.exe"
No errors output in console
You need to add the --grpc_out command line option, e.g. add
--grpc_out="C:\output\"
Note that it won't write any files if you don't have any services.
Here's a complete example. From a root directory, create:
An empty output directory
A tools directory with protoc.exe and grpc_csharp_plugin.exe
A protos directory with test.proto as shown below:
test.proto:
syntax = "proto3";
service StackOverflowService {
rpc GetAnswer(Question) returns (Answer);
}
message Question {
string text = 1;
string user = 2;
repeated string tags = 3;
}
message Answer {
string text = 1;
string user = 2;
}
Then run (all on one line; I've broken it just for readability here):
tools\protoc.exe -I protos protos\test.proto --csharp_out=output
--grpc_out=output --plugin=protoc-gen-grpc=tools\grpc_csharp_plugin.exe
In the output directory, you'll find Test.cs and TestGrpc.cs
Just an idle comment here for other that find this, the documentation about this is terribly out of date and just flat out wrong.
Installing Grpc.Tools does not install anything in a packages folder; that is legacy behaviour which is no longer true even on windows.
When you install Grpc.Tools it will be hidden away in your local package cache, which you can see by calling:
$ dotnet nuget locals all --list
info : http-cache: /Users/doug/.local/share/NuGet/v3-cache
info : global-packages: /Users/doug/.nuget/packages/
info : temp: /var/folders/xx/s2hnzbrj3yn4hp1bg8q9gb_m0000gn/T/NuGetScratch
The binaries you want will be in one of these folders.
The easiest way to do this is to download the Grpc.Tools package directly from nuget, and install it locally.
I've hacked up this little helper script to do that, which works on windows/mac/linux, which may ease the difficulty of getting starting with this for others:
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Mono.Unix;
namespace BuildProtocol
{
public class Program
{
private const string ToolsUrl = "https://www.nuget.org/api/v2/package/Grpc.Tools/";
private const string Service = "Greeter";
private static string ProtocolPath = Path.Combine("..", "protos");
private static string Protocol = Path.Combine(ProtocolPath, "helloworld.proto");
private static string Output = Path.Combine("..", "Greeter");
public static void Main(string[] args)
{
RequireTools().Wait();
var protoc = ProtocPath();
var plugin = ProtocPluginPath();
Console.WriteLine($"Using: {protoc}");
Console.WriteLine($"Using: {plugin}");
var command = new string[]
{
$"-I{ProtocolPath}",
$"--csharp_out={Output}",
$"--grpc_out={Output}",
$"--plugin=protoc-gen-grpc=\"{plugin}\"",
Protocol,
};
Console.WriteLine($"Exec: {protoc} {string.Join(' ', command)}");
var process = new Process
{
StartInfo = new ProcessStartInfo
{
UseShellExecute = false,
FileName = protoc,
Arguments = string.Join(' ', command)
}
};
process.Start();
process.WaitForExit();
Console.WriteLine($"Completed status: {process.ExitCode}");
}
public static async Task RequireTools()
{
if (!Directory.Exists("Tools"))
{
Console.WriteLine("No local tools found, downloading binaries from nuget...");
Directory.CreateDirectory("Tools");
await DownloadTools();
ExtractTools();
}
}
private static void ExtractTools()
{
ZipFile.ExtractToDirectory(Path.Combine("Tools", "tools.zip"), Path.Combine("Tools", "bin"));
}
private static async Task DownloadTools()
{
using (var client = new HttpClient())
{
Console.WriteLine($"Fetching: {ToolsUrl}");
using (var result = await client.GetAsync(ToolsUrl))
{
if (!result.IsSuccessStatusCode) throw new Exception($"Unable to download tools ({result.StatusCode}), check URL");
var localArchive = Path.Combine("Tools", "tools.zip");
Console.WriteLine($"Saving to: {localArchive}");
File.WriteAllBytes(localArchive, await result.Content.ReadAsByteArrayAsync());
}
}
}
private static string ProtocPath()
{
var path = Path.Combine("Tools", "bin", "tools", DetermineArch(), "protoc");
RequireExecutablePermission(path);
return WithExeExtensionIfRequired(path);
}
private static string ProtocPluginPath()
{
var path = Path.Combine("Tools", "bin", "tools", DetermineArch(), "grpc_csharp_plugin");
RequireExecutablePermission(path);
return WithExeExtensionIfRequired(path);
}
private static void RequireExecutablePermission(string path)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) return;
Console.WriteLine($"Ensuring +x on {path}");
var unixFileInfo = new UnixFileInfo(path);
unixFileInfo.FileAccessPermissions = FileAccessPermissions.UserRead | FileAccessPermissions.UserWrite | FileAccessPermissions.UserExecute;
}
private static string WithExeExtensionIfRequired(string path)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
path += ".exe";
}
return path;
}
private static string DetermineArch()
{
var arch = RuntimeInformation.OSArchitecture;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return WithArch("windows_", arch);
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
return WithArch("macosx_", arch);
}
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return WithArch("linux_", arch);
}
throw new Exception("Unable to determine runtime");
}
private static string WithArch(string platform, Architecture arch)
{
switch (arch)
{
case Architecture.X64:
return $"{platform}x86";
case Architecture.X86:
return $"{platform}x64";
default:
throw new ArgumentOutOfRangeException(nameof(arch), arch, null);
}
}
}
}
the following approach helped me :
Create a gRPC client and server in ASP.NET Core
in project, where .proto file located, edit the .csproj file
<ItemGroup>
....
<Protobuf Include="Shipping.proto" GrpcServices="Server" />
</ItemGroup>
rebuild the project, the all necessary .cs files will be added automaticaly
\obj\Debug\[TARGET_FRAMEWORK]\Shipping.cs
\obj\Debug\[TARGET_FRAMEWORK]\ShippingGrpc.cs

Unity find and delete all files named "Delete This File.txt"

I have a unity package with my folder structure pre-setup, but meant to be empty, in order to export the folders I put a file "Delete This File.txt" into every bottom folder in the structure to allow unity to export the folders, but I want to write a script that runs on startup which deletes these files, but i can't seem to get the script to find all the files throughout the various folders. How do i do this?
using UnityEngine;
using UnityEditor;
using System.IO;
[InitializeOnLoad]
public class Startup {
static Startup()
{
foreach (string file in Directory.GetFiles("Assets/")) {
if (file == "Delete This File.txt") {
Debug.Log (file);
} else {
// Do Nothing
}
}
}
}
Some changes are required in your code
[InitializeOnLoad]
public class Startup {
static Startup()
{
// unfortunately this is not available in NET 3.5
// foreach (string file in Directory.EnumerateFiles.....
foreach (string file in Directory.GetFiles("Assets", "Delete This File.txt", SearchOption.AllDirectories))
{
Debug.Log (file);
// File.Delete(file);
}
}
This approach uses the overload of Directory.GetFiles that takes the initial directory, the pattern to search for and the option to search all subdirectory of the root. The resulting strings are the full filenames to delete.
Also, in NET 4.0, there is a better option with Directory.EnumerateFiles as explained by the MSDN docs
The EnumerateFiles and GetFiles methods differ as follows: When you
use EnumerateFiles, you can start enumerating the collection of names
before the whole collection is returned; when you use GetFiles, you
must wait for the whole array of names to be returned before you can
access the array. Therefore, when you are working with many files and
directories, EnumerateFiles can be more efficient.
This can be done with the combination of Directory.GetFiles,Directory.GetDirectories and FileInfo classes. I modified Microsoft's RecursiveFileProcessor code example and added FileInfo and an if statement to make it find all files named "Delete This File.txt" and delete them.
using UnityEngine;
using UnityEditor;
using System.IO;
[InitializeOnLoad]
public class Startup
{
static Startup()
{
ProcessDirectory("Assets/");
}
public static void ProcessDirectory(string targetDirectory)
{
// Process the list of files found in the directory.
string[] fileEntries = Directory.GetFiles(targetDirectory);
foreach (string filePath in fileEntries)
{
FileInfo fileInfo = new FileInfo(filePath);
if (fileInfo.Name == "Delete This File.txt")
{
ProcessFile(filePath);
}
}
// Recurse into subdirectories of this directory.
string[] subdirectoryEntries = Directory.GetDirectories(targetDirectory);
foreach (string subdirectory in subdirectoryEntries)
{
ProcessDirectory(subdirectory);
}
}
// Insert logic for processing found files here.
public static void ProcessFile(string path)
{
Debug.Log("Processed file " + path);
//Delete File
File.Delete(path);
}
}
After discovering that Directory.EnumerateFiles wasn't an option for me I tried the same method with the get files, and found a solution that works. This code not only deletes the text file but the meta file that is associated with it, counting the number of times a text file was deleted and informing me how many were deleted in the log.
using UnityEngine;
using UnityEditor;
using System.IO;
/* Project Name : Ember Guard
* Script Name : RemoveDeleteFile
* Script Path : Assets/Editor/RemoveDeleteFile.cs
* Script Author : FaalFaazDov || Raisltin M. Thoreson
* Created On : 29/08/2016 14:24
* Modified On : N/A
* Version : 0.0.1Alpha
*/
/*************************************************************************
*
* Biophase Entertainment
* __________________
*
* [2016] Biophase Entertainment
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Biophase Entertainment and its suppliers,
* if any. The intellectual and technical concepts contained
* herein are proprietary to Biophase Entertainment
* and its suppliers and may be covered by Canadian and Foreign Patents,
* patents in process, and are protected by trade secret or copyright law.
* Dissemination of this information, reproduction of this material or attempting
* to read the content of these files is strictly forbidden unless prior written
* permission is obtained from Biophase Entertainment.
*
*/
[InitializeOnLoad]
public class Startup {
static Startup()
{
int x = 0;
string path = Application.dataPath;
string[] files = Directory.GetFiles (path, "Delete This File.txt", SearchOption.AllDirectories);
foreach (string f in files) {
File.Delete (f);
File.Delete (f + ".meta");
x++;
}
string fm;
if (x == 1) {
fm = "file";
} else {
fm = "files";
}
Debug.Log ("Deleted " + x + " " + fm + ".");
}
}

Categories

Resources