MacLochlainns Weblog

Michael McLaughlin's Technical Blog

Site Admin

Archive for the ‘Mac OS X’ Category

Excel 2011 Query MySQL

with 10 comments

I finally got around to finishing my testing of Excel 2011 querying MySQL. That meant installing and configuring Excel 2011 and MySQL 5.5.9 on Mac OS X (Snow Leopard). While installing Microsoft Office is pretty trivial, installing and configuring MySQL wasn’t. You can read about installing and configuring MySQL here. A quick test after this, led me to discover that you still need a third party ODBC, as covered in this earlier blog. You should take note that Microsoft’s future direction adopts Oracle ODBC, like the approach they’ve chosen with MySQL’s ODBC driver.

I downloaded and installed one of third party ODBC tool sets. I opted for OpenLink Software’s ODBC Driver. Instructions for the install with screen shots are in this blog page. The only downside of this was the discovery that Microsoft’s solution requires Rosetta, like Excel 2008. Rosetta enables Power PC application to run on Intel-based Mac OS X.

Launching the Database icon from Excel 2011, I configured the Data Source Name, which you can find here with screen shots. After you configure the Data Source Name, restarting Excel 2011 is the best choice because otherwise you may see several non-fatal errors.

The following screen shots show you how to establish a connection between Excel 2011 and MySQL, and how to query data from the MySQL database:

  1. After you click the Database icon, you see the following dialog. Select a Data Source Name and click the OK button to begin a query.

Querying MySQL from Excel 2010 #1

  1. The OpenLink MySQL Lite Login screen requires the user name and password. Click the Connect button to launch the Microsoft Query, which appears to be a native Power PC application that requires Rosetta to run it

Querying MySQL from Excel 2010 #2

  1. Microsoft Query appears to be a native Power PC application that requires Rosetta to run it. If you want to enter a query, click the SQL View button.

Querying MySQL from Excel 2010 #3

  1. Having clicked the SQL View button you now have a work area where you can enter a standard SQL SELECT statement, like the one below. Then, you click the Return Data button.

Querying MySQL from Excel 2010 #4

  1. This dialog lets you select where you want to put the return result set from the query. The default is the absolute cell reference of the top and left most cell, $A$1. Click the OK button to query and load the data into the worksheet.

Querying MySQL from Excel 2010 #5

  1. Now you can see the data in the worksheet. The only problem is the extraneous characters returned into the column headers of the table. While tedious, they’re easy to fix. The following illustrates the downloaded result set from the previous query:

Querying MySQL from Excel 2010 #6

  1. If you perform a query with a join operation, the column names are never displayed whether you provide aliases to the query or not. It means you have to convert the table to a range, remove the false headers, and recreate the table. This appears to be a limitation of Microsoft Query and unlike the behavior in Excel 2010 on Windows. Perhaps it’s all wrapped up in the emulation provided by Rosetta but I couldn’t find any information about what’s happening. That leaves me with pure speculation, which I never like. If you find the reason, post a comment with a link because everyone would benefit.

Querying MySQL from Excel 2010 #7

As always, I hope this helps those who want to work only in the Mac OS X environment. The risk is Rosetta because it will go away, the only question is when and whether the vendors will fix their dependency first or not. The problem with this solution is that Microsoft Query doesn’t return any tables when it appears that it should.

Written by maclochlainn

February 27th, 2011 at 2:51 am

Excel 2011 Needs ODBC Files

with one comment

I’d hoped for a better solution with Excel 2011 on Mac OS X but it appears we still need the third party drivers to connect Excel to MySQL. It’s the same as I reported earlier on Excel 2008. Here’s the message and you can click on it to go the web site and links to buy the drivers.

I tried getting away with installing the MySQL Connector/ODBC before downloading one of those recommended by Microsoft. I discovered that it didn’t work.

Therefore, I download and installed the OpenLink Software ODBC Software, instructions with screen shots are in this blog page. I discovered that this software support track isn’t purely native Mac OS X on Intel-based software because it requires Rosetta like Excel 2008. It also only connects with Microsoft Query, which appears to be a Power PC native application too, at least based on the interface and look and feel. I didn’t do much more research because I’ve concluded that connectivity isn’t ready for prime time on the Mac OS X platform. Microsoft still has more work to do.

Written by maclochlainn

February 10th, 2011 at 3:15 am

Mac OS X MySQL Install

with 102 comments

Installing MySQL 5.5.9 (updated for MySQL 5.5.16 and 5.5.18) on Mac OS X was on my list but it finally made the top. I needed to write instructions for a class that I teach because asking students who own a Mac to install VMWare and Windows before MySQL seems an unnecessary burden. Especially when you can install it directly on Mac OS X.

Mac OS X Mountain Lion (10.8.*) need to install XCode and Command Line Tools before installing MySQL. You can refer to this XCode installation and configuration post for those steps.

You can download MySQL for the Mac OS X. I downloaded the Mac OS X, Version 10.6 (x86, 64-bit) version for this installation. There were a couple shell syntax tricks beyond the instructions and then you need to configure database. That’s required because the database is installed with an unsecured anonymous and root account. After the step-by-step installation instructions, you’ll find the configuration steps to enable you to access the MySQL Monitor from a terminal session. It also configures your $PATH environment to enable you to start and stop the MySQL Daemon.

  1. After the download completes, open the file folder in the download directory.

  1. The open file folder and it will look like the following. Launch the mysql-5.5.9-osx 10.6-x86_64.pkg file, which installs the product.

  1. After launching the executable, you are now on the first page of the Install MySQL 5.5.9 installation application. Click the Continue button.

  1. This page contains the instructions, you can pause to read them or continue with these instructions. Click the Continue button to proceed.

  1. This page contains the General Public License (GPL). You agree or stop the installation. Click the Continue button to proceed.

  1. The following overlay dialog contains your agreement. Click the Agree button to proceed.

  1. There are fewer options in this installation than the Windows installation. While you can change the installation location, the software installs by default in the /usr/local/mysql directory. The installation requires that you have a mysql user account on the operating system, and you don’t need to do anything because one exists as part of the default Mac OS X installation. Click the Install button to proceed.

  1. This dialog requires the system administrator’s password. Enter the valid password and click the OK button to proceed.

  1. Depending on the system, this could take more than a minute. All you can do it wait.

  1. This page tells you that you’ve completed the installation. Click the Close button to proceed.

  1. This step requires that you return to the download folder, shown in Step #2 above. Launch the MySQLStartupItem.pkg and you’ll see the following MySQL Startup Item Installer dialog. Click the Continue button to proceed.

  1. This page contains the instructions for the MySQL Startup software, you can pause to read them or continue with these instructions. Click the Continue button to proceed.

  1. This page asks if you want to change the directory. I’d recommend you leave it as the default because it requires the System Administrator’s password to start and stop the database. It should also start for you every time you boot the machine. Click the Continue button to proceed.

  1. Like Step #8, this dialog requires the system administrator’s password. Enter the valid password and click the OK button to proceed.

  1. You could see a progress dialog box but generally it happens so fast you should land at the Installation was Successful dialog. Click the Close button to proceed.

  1. This step requires that you return to the download folder, shown in Step #2 above. Launch the MySQL.prefPane and you’ll see the following MySQL Preferences dialog. Click the Install button to proceed.

  1. Like Step #8 and #14, this dialog requires the system administrator’s password. Enter the valid password and click the OK button to proceed.

  1. Don’t click in the automatic start button unless you’re sure. Otherwise, there’s a lot of cleanup to be able to return to this point and start or stop the server as required. This is the last screen, you should click the Start MySQL Server button to start MySQL. While installing MySQL 5.5.18 I discovered that the service menu is no longer installed in the Preferences, and you must start it manually.

You can start and stop the service by opening your System Preferences, where you’ll find them in the bottom Other row. If the intent was to have it start automatically, sometimes the permissions are incorrect. You’ll get the following error in MySQL 5.5.9 but not in MySQL 5.5.16 because the MySQL DMG file is fixed. You can skip the instructions until you get to Configure User’s Shell Environment below:

"/Library/StartupItems/MySQLCOM" has not been started because it does not have the proper security settings.

You can fix this by changing the permissions manually in a Terminal Session. Launch a Terminal Session from your Utilities folder inside your Applications folder.

Change directory to the /Library/StartupItems/MySQLCOM directory. Then, list the files. These commands should do the trick for you:

cd /Library/StartupItems/MySQLCOM
ls -al

If you see these permissions, you have problem because the group for startup files should be wheel not staff:

drwxr-xr-x  4 root  staff   136 Jan 20 13:46 .
drwxr-xr-x  4 root  wheel   136 Feb  9 21:11 ..
-rwxr-xr-x  1 root  staff  1300 Jan 20 13:46 MySQLCOM
-rw-r--r--  1 root  staff   469 Jan 20 13:46 StartupParameters.plist

You can change the files with this command:

sudo chown root:wheel *

However, now you need to step up the directory tree one level to /Library/StartupItems, and change the ownership of:

drwxr-xr-x   4 root  staff   136 Jan 20 13:46 MySQLCOM

There are two commands to do this. The first changes directory by moving to the parent directory in the hierarchy (the parent directory is represented by two dots). The second changes the group ownership of the MySQLCOM directory.

cd ..
sudo chown root:wheel MySQLCOM

Now you need to configure your shell environment and harden the database. Hardening means securing accounts with passwords. They’re covered in the next two sections.

Configure User’s Shell Environment

Assuming you accepted the defaults, you should be able to copy the required instructions directly into a .bash_login file if one exists. Unless you’ve created one before there won’t be a file. Mac OS X doesn’t automatically create the file. If you don’t have the file, you can create one with the following syntax:

touch .bash_login

You can open the file with the vi editor or a text editor of your choice. MySQL 5.5.9 installed in /usr/local/mysql, which has changed to /usr/local/mysql-version as noted below. You can copy the following contents into the file for MySQL 5.5.16 but will need to change the file for earlier or later releases (added sudo per Don McArthur’s comment):

# Set the MySQL Home environment variable to point to the root directory of the MySQL installation.
export set MYSQL_HOME=/usr/local/mysql-5.5.16-osx10.6-x86_64
 
# Add the /bin directory from the MYSQL_HOME location into your $PATH environment variable.
export set PATH=$PATH:$MYSQL_HOME/bin
 
# Create aliases that make it easier for you to manually start and stop the MySQL Daemon.
alias mysqlstart="sudo /Library/StartupItems/MySQLCOM start"
alias mysqlstop="sudo /Library/StartupItems/MySQLCOM stop"

Changes between MySQL 5.5.16 and 5.5.18 introduce a new directory structure, you need to use the following in the .bash_login file (added sudo and status per Don McArthur’s comments):

# Set the MySQL Home environment variable to point to the root directory of the MySQL installation.
export set MYSQL_HOME=/usr/local/mysql-5.5.18-osx10.6-x86_64
 
# Add the /bin directory from the MYSQL_HOME location into your $PATH environment variable.
export set PATH=$PATH:$MYSQL_HOME/bin
 
# Create aliases that make it easier for you to manually start and stop the MySQL Daemon.
alias mysqlstart="sudo /Library/StartupItems/MySQLCOM/MySQLCOM start"
alias mysqlstop="sudo /Library/StartupItems/MySQLCOM/MySQLCOM stop"
alias mysqlstatus="ps aux | grep mysql | grep -v grep"

As pointed out by Shashank’s comment, you should now use the following aliases:

alias mysqlstart='sudo /usr/local/mysql/support-files/mysql.server start'
alias mysqlstop='sudo /usr/local/mysql/support-files/mysql.server stop'

You need to save the file and close and restart a new Terminal session to place these environment variables in scope. You could also run the following to put them in scope without closing and opening the terminal:

. ./.bash_login

The preceding command sources the environment file into active memory. This should configure your environment. After restarting the shell, you should be able to run this command to confirm the new environment:

which -a mysql

It should return:

/usr/local/mysql-5.5.16-osx10.6-x86_64/bin/mysql

Secure the Database

This is presently necessary because of the different file structure in a Mac OS X MySQL install, which disables the mysql_secure_installation file from running successfully. You can manually edit the file or follow these steps.

You need to connect to the database as the privileged super user, root user. This is simple because the installation doesn’t set any passwords. You open another Terminal session to make these changes or you could install MyPHPAdmin or MySQL Workbench. The tools work as well in fixing the majority of issues.

mysql -uroot

Once connected to the database as the root user, you can confirm that passwords aren’t set and an insecure anonymous user account has been previously configured. You do that by connecting to the mysql database, which is the database catalog for MySQL. You do that by running the following command:

USE mysql;

You can query the result set with the following query:

SELECT USER, password, host FROM USER\G

You should see the following output plus the user’s name preceding the MacPro (or iMac.local) host name value:

*************************** 1. row ***************************
    user: root
password: 
    host: localhost
*************************** 2. row ***************************
    user: root
password: 
    host: MacPro.local
*************************** 3. row ***************************
    user: root
password: 
    host: 127.0.0.1
*************************** 4. row ***************************
    user: root
password: 
    host: ::1
*************************** 5. row ***************************
    user: 
password: 
    host: localhost
*************************** 6. row ***************************
    user: 
password: 
    host: MacPro.local

You now need to change the password for the root user. I would suggest that you do this with the SQL command rather than a direct update against the data dictionary tables. The syntax to fix the root user account require you enter the user name, an @ symbol, and complete host values, like:

SET PASSWORD FOR 'root'@'localhost' = password('cangetin');
SET PASSWORD FOR 'root'@'MacPro.local' = password('cangetin');
SET PASSWORD FOR 'root'@'127.0.0.1' = password('cangetin');
SET PASSWORD FOR 'root'@'::1' = password('cangetin');

You should be able to drop both anonymous user rows with the following syntax, but I did encounter a problem. Assuming you may likewise encounter the problem, the fix follows the first commands you should try:

DROP USER ''@'localhost';
DROP USER ''@'MacPro.local';

If either of the anonymous accounts remain in the USER table, you can manually drop them from the database catalog. This syntax will get rid of them:

DELETE FROM USER WHERE LENGTH(USER) = 0;

You’ve completed the configuration and can now type quit; to exit the MySQL Monitor. To reconnect, you’ll now need a password, like this:

mysql -uroot -pcangetin

Also, don’t forget to use a real password. The one shown here is trivial, which means easy to hack. Use something that others might not guess.

Configure my.cnf file

You can copy one of the sample configuration files as a starting point (as provided by Don McArthur’s comment):

sudo cp /usr/local/mysql/support-files/my-huge.cnf /etc/my.cnf

Starting and Stopping the Database

You can manually start the database server with the following command, which you defined as aliases in your .bash_login shell script:

mysqlstart

Stopping it is also straightforward, you do this:

mysqlstop

You can check it’s status with this command:

mysqlstatus

Written by maclochlainn

February 10th, 2011 at 2:57 am

Posted in Mac,Mac OS X,MAMP,MySQL

Prepared Statement Failure

with 3 comments

One of my students asked for some help on developing a MySQL stored procedure that would conditionally drop a foreign key constraint. I put together a quick example, which compiled fine but failed at run time. With some investigation it appears that either the MySQL 5.5 Documentation in Section 12.6 is incorrect or you can’t ALTER TABLE inside a MySQL Prepared Statement with placeholders.

A subsequent test showed me that you couldn’t use ALTER TABLE statement in a prepared statement outside of a stored procedure. I logged Bug #59604 with my other test case, and put the test case there. They closed the bug and validated what I suspected and clarified what I missed, you can’t use placeholders in prepared DDL statements.

The following is the test code example that failed:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
DROP PROCEDURE IF EXISTS dropForeignKey;
 
DELIMITER $$
 
CREATE PROCEDURE dropForeignKey
( pv_database   VARCHAR(64)
, pv_table      VARCHAR(64)
, pv_constraint VARCHAR(64))
BEGIN
 
  /* Declare a local variable for the SQL statement. */
  DECLARE stmt VARCHAR(1024);
 
  /* Set a session variable with two parameter markers. */
  SET @SQL := 'ALTER TABLE ? DROP FOREIGN KEY ?';
 
  /* Assign the formal parameters to session variables because prepared statements require them. */
  SET @sv_table := pv_table;
  SET @sv_constraint := pv_constraint;
 
  /* Check if the constraint exists. */  
  IF EXISTS (SELECT NULL
             FROM   information_schema.referential_constraints
             WHERE  constraint_schema = pv_database
             AND    TABLE_NAME = pv_table
             AND    constraint_name = pv_constraint)
  THEN
 
    /* Dynamically allocated and run statement. */
    PREPARE stmt FROM @SQL;
    EXECUTE stmt USING @sv_table, @sv_constraint;
    DEALLOCATE PREPARE stmt;
  END IF;
 
END;
$$
 
DELIMITER ;

Calling this with the following syntax:

CALL dropForeignKey(DATABASE(),'telephone','telephone_fk4');

It raised the following error message.

ERROR 1064 (42000): You have an error IN your SQL syntax; CHECK the manual that corresponds TO your MySQL server version FOR the RIGHT syntax TO USE near '? DROP FOREIGN KEY ?' at line 1

Based on the comment from Bug #59604, I concluded that the ALTER TABLE statement doesn’t support using session variables. However, the CONCAT() function solves the problem. Given this is a DDL command, and any extraneous quoting would simply fail parsing rules because of the CONCAT function, SQL injection doesn’t appear a threat.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
DROP PROCEDURE IF EXISTS dropForeignKey;
 
DELIMITER $$
 
CREATE PROCEDURE dropForeignKey
( pv_database  VARCHAR(64)
, pv_table      VARCHAR(64)
, pv_constraint VARCHAR(64))
BEGIN
 
  /* Declare a local variable for the SQL statement. */
  DECLARE stmt VARCHAR(1024);
 
  /* Set a session variable with two parameter markers. */
  SET @SQL := CONCAT('ALTER TABLE ',pv_table,' DROP FOREIGN KEY ',pv_constraint);
 
  /* Check if the constraint exists. */    
  IF EXISTS (SELECT NULL
             FROM   information_schema.referential_constraints
             WHERE  constraint_schema = pv_database
             AND    TABLE_NAME = pv_table
             AND    constraint_name = pv_constraint)
  THEN
 
    /* Dynamically allocated and run statement. */
    PREPARE stmt FROM @SQL;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
  END IF;
 
END;
$$
 
DELIMITER ;

A more useful approach would be to drop all foreign keys that reference a table. Here’s how you would accomplish that.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
-- Conditionally drop the procedure.
DROP PROCEDURE IF EXISTS dropForeignKeys;
 
-- Change delimiter to create procedure.
DELIMITER $$
 
-- Create procedure.
CREATE PROCEDURE dropForeignKeys
( pv_database          VARCHAR(64)
, pv_referenced_table  VARCHAR(64))
BEGIN
 
  /* Declare local statement variables. */
  DECLARE lv_stmt VARCHAR(1024);
 
  /* Declare local cursor variables. */
  DECLARE lv_table_name       VARCHAR(64);
  DECLARE lv_constraint_name  VARCHAR(64);
 
  /* Declare control variable for handler. */
  DECLARE fetched       INT DEFAULT 0;
 
  /* Declare local cursor. */
  DECLARE foreign_key_cursor CURSOR FOR
    SELECT   rc.table_name
    ,        rc.constraint_name
    FROM     information_schema.referential_constraints rc
    WHERE    constraint_schema = pv_database
    AND      referenced_table_name = pv_referenced_table
    ORDER BY rc.table_name
    ,        rc.constraint_name;
 
  /* Declare a not found record handler to close a cursor loop. */
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET fetched = 1;
 
  /* Open a local cursor. */  
  OPEN foreign_key_cursor;
  cursor_foreign_key: LOOP
 
    FETCH foreign_key_cursor
    INTO  lv_table_name
    ,     lv_constraint_name;
 
    /* Place the catch handler for no more rows found
       immediately after the fetch operation.          */
    IF fetched = 1 THEN LEAVE cursor_foreign_key; END IF;
 
    /* Set a SQL statement by using concatenation. */
    SET @SQL := CONCAT('ALTER TABLE ',lv_table_name,' DROP FOREIGN KEY ',lv_constraint_name);
 
    /* Prepare, run, and deallocate statement. */
    PREPARE lv_stmt FROM @SQL;
    EXECUTE lv_stmt;
    DEALLOCATE PREPARE lv_stmt;
 
  END LOOP cursor_foreign_key;
  CLOSE foreign_key_cursor;  
 
END;
$$
 
-- Reset delimiter to run SQL statements.
DELIMITER ;

You would test it with this call:

CALL dropForeignKeys(DATABASE(),'system_user');

As always, I hope this helps somebody.

Written by maclochlainn

January 19th, 2011 at 1:39 am

Posted in Mac OS X,MAMP,MySQL,PSM

Handling Bash Parameters

with 2 comments

Bash shell or shells in general hang on details. An ex-student was trying to sort something out in Learning the bash Shell, 3rd Edition, which isn’t on my short list of good shell scripting books. I concur more or less with the comment on Amazon.com that there are too few examples in the book. I think the free examples here may serve folks in lieu of a book.

Anyway, the student’s problem involved processing multiple word parameters in an array. They were confused about how to handle ${*}, ${@} "${*}" and "${@}" when assigning them into an array for subsequent processing. By the way, I did find a decent explanation of the concept on Page 89 in my copy of the book. Though my copy is a 2nd Edition.

Here’s a dressed up sample of what they were attempting to do:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/bin/bash
 
# Print header information.
echo "Begin Program!"
echo ""
 
# Count the call parameters.
echo "Count call parameters [" ${#} "]"
echo ""
 
# Declare an array of delimited parameters.
ARRAY=(${@})
 
# Declare a numeric constant of array elements.
ELEMENTS=${#ARRAY[@]}
 
# Does the parameter account agree with array elements.
if [[ ${#} = ${#ARRAY[@]} ]]; then
  echo "Parameters match exploded array elements."
else
  echo "Parameters ["${#}"] don't match exploded array elements ["${ELEMENTS}"]."
fi
 
# Echo line break.
echo ""
 
# Echo the parameter list.
for (( i = 0; i < ${ELEMENTS}; i++ )); do
  echo "  ARRAY["${i}"]=["${ARRAY[${i}]}"]"
done
 
# Print footer information.
echo ""
echo "End Program!"

With the ARRAY=(${@}) assignment on line #12, they exploded the elements into individual words. They thought that the IFS (Internal Field Separator) environment variable was defined wrong but it wasn’t.

They called the program like this from the command-line:

sample.sh "Me too" "You too"

Then, they got this syntax and were surprised.

Begin Program!
 
Count call parameters [ 2 ]
 
Parameters [2] don't match exploded array elements [4].
 
  ARRAY[0]=[Me]
  ARRAY[1]=[too]
  ARRAY[2]=[You]
  ARRAY[3]=[too]
 
End Program!

They were close. The ARRAY=(${@}) assignment on line #12. There attempt to fix it with ARRAY=(${*}) led nowhere because it’s more or less the same and explodes into 4 words. To their credit, they put quotes around it like this ARRAY=("${*}") and got two parameters but one array element, as shown below:

Begin Program!
 
Count call parameters [ 2 ]
 
Parameters [2] don't match exploded array elements [1].
 
  ARRAY[0]=[Me too You too]
 
End Program!

What they needed was ARRAY=("${@}") on line #12 to explode quote delimited parameters. Here’s a complete working example of the final code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/bin/bash
 
# Print header information.
echo "Begin Program!"
echo ""
 
# Count the call parameters.
echo "Count call parameters [" ${#} "]"
echo ""
 
# Declare an array of delimited parameters.
ARRAY=("${@}")
 
# Declare a numeric constant of array elements.
ELEMENTS=${#ARRAY[@]}
 
# Does the parameter account agree with array elements.
if [[ ${#} = ${#ARRAY[@]} ]]; then
  echo "Parameters match exploded array elements."
else
  echo "Parameters ["${#}"] don't match exploded array elements ["${ELEMENTS}"]."
fi
 
# Echo line break.
echo ""
 
# Echo the parameter list.
for (( i = 0; i < ${ELEMENTS}; i++ )); do
  echo "  ARRAY["${i}"]=["${ARRAY[${i}]}"]"
done
 
# Print footer information.
echo ""
echo "End Program!"

Changing that one element yields their desired output:

Begin Program!
 
Count call parameters [ 2 ]
 
Parameters match exploded array elements.
 
  ARRAY[0]=[Me too]
  ARRAY[1]=[You too]
 
End Program!

As always, I hope this helps some folks.

Written by maclochlainn

January 2nd, 2011 at 1:40 am

Excel 2011 supports UDFs?

with 18 comments

I had a chance (30 minutes) to play with Excel 2011 on the Mac OS X today. I was shocked to discover that Excel 2011 didn’t appear to support User-Defined Functions (UDFs) like Excel 2010 for Windows. My understanding was that this release would be one where it implemented Visual Basic for Applications (VBA) like Windows. Initially I thought it didn’t but I bought my own copy, did a full install with Visual Basic, and it appears that Microsoft has delivered. Oops, my bad for assuming the machine I played on originally had a solid installation. It appears to have had only a standard installation.

Watch out because UDFs fail with a #NAME! error on a standard install of Excel 2011. While they’re found in the Insert Function dialog in both cases, they only appear to work with a full installation. The downside for Insert Function is that, like Excel 2008, it has no quick poplist to narrow the function choices to groups. We have the big list once more.

Here are my test functions:

Function hello()
  hello = "Hello World!"
End Function
 
Function hellowhom(nameIn As Variant)
  hellowhom = "Hello " + CStr(nameIn) + "!"
End Function

I think I found the trick to get Excel 2011 recognize and run User-Defined Functions. Make sure you do a custom installation and check Visual Basic for Application. Anyway, you can test these functions like that shown below. Column A contains the text of the formulas (a preceding single quote does that), and column B contains actual function calls.

Enabling the Developer ribbon took a few moments when I got my own copy. I figured that updating this was better than making a new post on the blog and linking them. It’s a three step process.

  1. Navigate to the Excel menu item and select Preferences…, as shown below.

  1. In the Excel Preferences shown below, click the Ribbon icon.

  1. In the Show or hide tabs, or drag them into the order you prefer: box shown below, enable the Developer checkbox.

It’s awesome, now accountants and economists can switch to Mac OS X without having to host a virtual machine with Microsoft Excel.

Written by maclochlainn

November 4th, 2010 at 3:40 pm

VMWare Fusion Permissions

with 3 comments

It’s always interesting when I have to sort out problems with VMWare Fusion on my Mac OS X. Right, as you guessed, interesting means frustrating. 😉 What started the whole thing was my investigating why VMWare networking would sometimes not start. I noticed the problem began after my upgrade to VMWare Fusion 3.1.0 (261058).

Rather than reboot the Mac OS X, which has fixed the problem, I tried to restart the service after closing my VMs. You can find how to do that in this older post of mine.

When I tried to restart it with the following command:

# sudo /Library/Application\ Support/VMware\ Fusion/boot.sh  --restart

I got the following error on VMWare file permissions:

VMware Fusion 261058: Shutting down VMware Fusion: 
Stopped DHCP service on vmnet1
Disabled hostonly virtual adapter on vmnet1
Stopped DHCP service on vmnet8
Stopped NAT service on vmnet8
Disabled hostonly virtual adapter on vmnet8
Stopped all configured services on all networks
No matching processes were found
No matching processes were found
No matching processes were found
No matching processes were found
No matching processes were found
No matching processes were found
(kernel) Kext com.vmware.kext.vmcrosstalk not found for unload request.
Failed to unload com.vmware.kext.vmcrosstalk - (libkern/kext) not found.
(kernel) Kext com.vmware.kext.vmmon not found for unload request.
Failed to unload com.vmware.kext.vmmon - (libkern/kext) not found.
 
VMware Fusion 261058: Starting VMware Fusion: 
2010-06-10 22:22:30.588 repair_packages[455:607] PackageKit: *** Missing bundle identifier: /Library/Receipts/vpn.pkg
Verifying files from package 'com.vmware.fusion.application' on '/'.
	Permissions differ on "Library/Application Support/VMware Fusion/VMDKMounter.app/Contents/MacOS/vmware-vmdkMounter", should be -rwxr-xr-x , they are -rwsr-xr-x .
	Warning: SUID file 'Library/Application Support/VMware Fusion/VMDKMounter.app/Contents/MacOS/vmware-vmdkMounter' has been modified and will not be repaired.
Finished verifying files from package 'com.vmware.fusion.application' on '/'.
Started network services
Verifying and re-installing files from /Library/Application Support/VMware Fusion/thnuclnt

Navigating to the directory, an ls -al found the two files below and their respective permissions.

drwxr-xr-x  4 root  wheel      136 Jun 10 22:51 .
drwxr-xr-x  5 root  wheel      170 May 27 21:22 ..
-rwsr-xr-x  1 root  wheel  1593620 May 21 03:51 vmware-vmdkMounter
-rwsr-xr-x  1 root  wheel  1475396 May 21 03:51 vmware-vmdkMounterTool

I thought perhaps both files required the same permissions but I was wrong. If you change the permissions on the vmware-vmdkMounterTool file, you’ll raise an error telling you that it should be -rwsr-xr-x. If you make that same mistake too, I’ve got the reset syntax at the bottom of the post.

You should only change the file permissions of vmware-vmdkMounter file. The following syntax lets you remove the sticky bit from the user permissions but you’ll need the root password (the administrator password).

sudo chmod u=rwx,go=rx vmware-vmdkMounter

That should leave you with the following permissions:

drwxr-xr-x  4 root  wheel      136 Jun 10 22:51 .
drwxr-xr-x  5 root  wheel      170 May 27 21:22 ..
-rwxr-xr-x  1 root  wheel  1593620 May 21 03:51 vmware-vmdkMounter
-rwsr-xr-x  1 root  wheel  1475396 May 21 03:51 vmware-vmdkMounterTool

When you restart you should get the following pseudo clean output. Pseudo because apparently the two errors are not meaningful. At least, I couldn’t find anything on them and VMWare Fusion now works. I’ll probably investigate this a bit more later, and I’ll update anything in this post. If you know something, post it as a comment to help everybody.

VMware Fusion 261058: Shutting down VMware Fusion: 
Stopped DHCP service on vmnet1
Disabled hostonly virtual adapter on vmnet1
Stopped DHCP service on vmnet8
Stopped NAT service on vmnet8
Disabled hostonly virtual adapter on vmnet8
Stopped all configured services on all networks
No matching processes were found
No matching processes were found
No matching processes were found
No matching processes were found
No matching processes were found
No matching processes were found
(kernel) Kext com.vmware.kext.vmcrosstalk not found for unload request.
Failed to unload com.vmware.kext.vmcrosstalk - (libkern/kext) not found.
(kernel) Kext com.vmware.kext.vmmon not found for unload request.
Failed to unload com.vmware.kext.vmmon - (libkern/kext) not found.
 
VMware Fusion 261058: Starting VMware Fusion: 
2010-06-10 22:58:45.276 repair_packages[861:607] PackageKit: *** Missing bundle identifier: /Library/Receipts/vpn.pkg
Verifying files from package 'com.vmware.fusion.application' on '/'.
Finished verifying files from package 'com.vmware.fusion.application' on '/'.
Started network services
Verifying and re-installing files from /Library/Application Support/VMware Fusion/thnuclnt

If you fat fingered the resetting command and also changed the vmware-vmdkMounterTool file permissions, you can reset them to shared user by using the following syntax:

sudo chmod u=rwxs,go=rx vmware-vmdkMounterTool

As always, I hope this helps others.

Written by maclochlainn

June 10th, 2010 at 11:28 pm

QuickTime Pro on Windows

with 5 comments

I popped for QuickTime Pro for Windows 7 ($29.99). The reason for doing so, was to create native screen capture that would integrate with Mac Adobe Premiere Pro, CS4. That’s because my Camtasia output didn’t work due to a compression mismatch.

Unfortunately, QuickTime Pro on Windows 7 doesn’t support screen capture. Quite a difference between what the product does on a Mac OS X versus a Windows 7 OS. I thought only Microsoft shorted users on the other platform, like Microsoft Excel 2007 versus Microsoft Excel 2008 (a far inferior product). Oops, I was wrong! Apple does it too. 🙁

Written by maclochlainn

May 22nd, 2010 at 10:47 am

Seagate 1TB Disk Fails

with 5 comments

Two posts in a row on hardware failures – whew :-(. Just after fixing my Mac Pro Video card, one of my 1 TB Seagate Barracuda hard drives failed. Naturally, it’s the one with half a terabyte of virtual machines.

First thing I checked was whether or not the disk still spun. It did but was not recognized by the Mac OS X or Windows 7 OS. Then, I swapped the disk controller card with another one of the same model numbered disks. The Mac OS X recognized it and launched Disk Utility but with a catch. I’d need to re-partition it, which would trash the important data.

I’m now working on recovering it byte-by-byte, big ouch! As time consuming as it is, I’m going to start performing weekly backups to DVD on my test and development machine.

To add insult to injury, I found out that Seagate knew about the problem but kept it quiet. Hoping the data recovery works, I’ll do an RMA afterward on the broken drive, which also makes a clicking noise after the disk controller failure.

This is the Seagate Barracuda 7200.11 (1 Terabyte) Drive, Model #ST3100340AS, which was heralded for its breakthrough four 250 GB platters. It is prone to failure. You may avoid failure by applying a firmware update but only before the disk fails. I’ve got two more of these that require a firmware update. Also, my eroded confidence in Seagate causes me to worry whether they’re in my External Seagate drives. I use them for time machines. You can read the story from January 2009, which unfortunately I missed before now.

A quick update, you can download DriveDetect from Seagate if you’re running the Windows OS but they’ve not got a utility for Mac OS X. You’ll have to manually pull the drives. For the USB drives, it appears that you’ll need a PC to run their utility.

Written by maclochlainn

May 1st, 2010 at 3:14 pm

Target Disk Mode

without comments

It’s been a terribly busy three weeks, needless to say when I got back to working my Mac Pro video card failed. That was Saturday, and I’m waiting on the replacement card. Thank goodness for AppleCare because the card is still $200.

In the meantime, I was stuck without being able to use Screen Sharing. A friend, Kyle, told me how to use Target Disk Mode to boot my Mac Pro on my MacBook Pro, which let me enable Screen Sharing without trying to sort through the configuration files. This basically lets me use my MacBook Pro as a bridge until I get the new video card.

I figured it would be nice to label how to do it. First, you’ll need a FireWire 800 cable or with older equipment a FireWire 400 cable will work. Connect the two machines, then:

  1. Boot the disabled machine in Disk Target Mode by holding down the “T” key when turning on the physical machine.
  2. Boot the target console by holding down the Option key.
  3. You’ll see two disks, one should be the standard silver disk icon and the other a gold remote disk icon. Use the right arrow key to select the gold remote disk, then click the return key.

Your target machine is now booted off the remote machine. You can now navigate to System Preferences, choose Sharing, and check the Checkbox for Screen Sharing. Now you can shutdown both systems and use screen sharing or continue to work this way. It’s really your preference. I like screen sharing because then I can use the resources from both machines.

This may be old hat to many but I’ve got a hunch it’s news to others. While I knew there was a way to do this, I’d never had to try it until now.

An update 4/27/10, AppleCare got me the replacement video card. I installed it and it worked like a charm.

Written by maclochlainn

April 26th, 2010 at 10:14 pm